您的问题似乎是您在每次函数调用时制作内存器的本地副本,然后销毁它。
这是一个简单的单参数版本的记忆器,似乎有效:
#include <iostream>
#include <functional>
#include <unordered_map>
template<typename Sig, typename F=Sig* >
struct memoize_t;
template<typename R, typename Arg, typename F>
struct memoize_t<R(Arg), F> {
F f;
mutable std::unordered_map< Arg, R > results;
template<typename... Args>
R operator()( Args&&... args ) const {
Arg a{ std::forward<Args>(args)... }; // in tuple version, std::tuple<...> a
auto it = results.find(a);
if (it != results.end())
return it->second;
R retval = f(a); // in tuple version, use a tuple-to-arg invoker
results.emplace( std::forward<Arg>(a), retval ); // not sure what to do here in tuple version
return retval;
}
};
template<typename F>
memoize_t<F> memoize( F* func ) {
return {func};
}
int foo(int x) {
static auto mem = memoize(foo);
auto&& foo = mem;
std::cout << "processing...\n";
if (x <= 0) return foo(x+2)-foo(x+1); // bwahaha
if (x <= 2) return 1;
return foo(x-1) + foo(x-2);;
}
int main() {
std::cout << foo(10) << "\n";
}
活生生的例子 http://ideone.com/oxLz7P
注意foo(10)
仅调用 10 次foo
.
这也承认:
#define CAT2(A,B,C) A##B##C
#define CAT(A,B,C) CAT2(A,B,C)
#define MEMOIZE(F) \
static auto CAT( memoize_static_, __LINE__, F ) = memoize(F); \
auto&& F = CAT( memoize_static_, __LINE__, F )
int foo(int x) {
MEMOIZE(foo);
std::cout << "processing...\n";
if (x <= 0) return 0;
if (x <= 2) return 1;
return foo(x-1) + foo(x-2);;
}
对于喜欢宏的人来说。
三步版本可能会更好。
首先,前奏是函数和记忆器包装器的前向声明。
其次,在函数内部,为函数名起一个别名,以便递归调用时使用记忆函数。
三、函数声明后,为函数名起一个别名,以便外部调用also使用记忆版本。
上面的代码只记住递归调用,而不是初始调用。