c++中的记忆函数包装器
Memoization functor wrapper in c++
这是我为函数编写的通用记忆包装器。它使用了tuplehash。
template<typename R, typename... Args>
class memofunc{
typedef R (*func)(Args...);
func fun_;
unordered_map<tuple<Args...>, R, tuplehash::hash<tuple<Args...> > > map_;
public:
memofunc(func fu):fun_(fu){}
R operator()(Args&&... args){
auto key = make_tuple(std::forward<Args>(args)...);
auto q = map_.find(key);
if(q == map_.end()){
R res = fun_(std::forward<Args>(args)...);
map_.insert({key,res});
return res;
}else{
return q->second;
}
}
};
斐波那契数列的用法示例。
long long fibo(long long x){
static memofunc<long long, long long> memf(fibo);
// try to replace fibo with this new fibo but doesn't work, why?
// function<long long(long long)> fibo = memf;
if(x <= 2) return 1;
// this works but involves changing the original code.
// how to write code such that I dont need to manually add this code in?
return memf(x-1) + memf(x-2);
// old code
// return fibo(x-1) + fibo(x-2);
}
问题是,理想情况下,我可以在递归函数的开头添加几行,然后完成记忆。但是简单的替换不起作用,这就是我卡住的地方。
你的问题似乎是你在每个函数调用时都做了一个备忘录的本地副本,然后销毁它。
这是你的记忆器的一个简单的单参数版本,似乎有效:
#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";
}
生活例子
注意foo(10)
只调用foo
10次。
这也允许:
#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);;
}
对于喜欢使用宏的人来说。
3步版本可能更好。
首先,以函数和记忆器包装器的前向声明作为前奏。
第二,在函数内部,函数名的别名,因此递归调用使用记忆函数。
第三,在函数声明之后,函数名的别名,因此外部调用也使用记忆版本。
上面的代码只存储递归调用,不存储初始调用。
相关文章:
- 我的包装函数缺少变量?
- 为什么这个"ctypes"包装函数的返回值是"c_long(0)"而不是&quo
- 如何将包装类的对象用作包装函数中的参数
- 包装C++函数以使用 SWIG 获取 Lua 字符串表
- 带有默认参数的宏包装函数调用
- 如何使用模板函数参数编写包装函数,该功能可以采用超载的成员函数
- 创建一个__cdecl以在 C++ 上__thiscall包装函数
- 在C++中实现和包装函数组合以进行惰性计算
- c++11:如何编写一个包装函数来生成"std::function"对象
- 为什么 Dart 中的原生包装函数与非常轻量级的函数相比"DEFINE NATIVE ENTRY"如此重量级?
- 在 C++ 中使用 map,并提供包装函数以在 C 语言中使用它
- 包装函数只有在链接为静态时才从链接库调用
- 尝试包装函数返回值时出现"<类名>不提供调用运算符"错误
- 交叉编译器/平台裸包装函数,无条件跳转到函数指针
- realloc C 函数的可能包装函数有什么错误?
- 包装 C++ 函数以在 C# 中使用
- 采用"pass by reference"值的递归函数的包装函数
- C++包装函数(宏)来访问 COM 对象属性
- 包装函数指针和函数对象在泛型代码中是如何工作的
- 在c++类中直接包装函数