【发布时间】:2014-01-29 13:21:36
【问题描述】:
博文Automatic Memoization in c++0x 提供了一个函数,用于生成现有函数的记忆版本。该博客文章和相关代码之前已在 stackoverflow 上讨论过(例如What does this C++11 code do?),但是,这些解决方案都无法提供一个完全通用的记忆器,它也能够正确记忆递归函数。
当然,通过使用类似这样的东西来改变递归调用是有技巧的(假设我们已经有一个记忆器,比如博客文章中提到的那个叫做 memoize 的记忆器):
std::function<int (int)> f;
int fib(int n) {
if (n < 2) return n;
return f(n-1) + f(n-2);
}
int main(void) {
f = memoize(std::function<int (int)>(fib));
}
但这感觉更像是一种解决方法,而不是一个适当的解决方案,因为我们仍然需要访问我们想要记忆的功能。一个适当的解决方案应该能够完全记忆任何功能,包括在某些库中定义的功能。但是,产生这样的解决方案似乎超出了我的能力范围(假设它是可能的),因此我问:
一个真正通用的记忆功能可能吗?
如何实现这样的壮举?
如果这是不可能的,是否至少有一种方法可以概括上述方法。类似于(无法编译且不是有效的 C++):
int fib(int n){
if (n < 2) return n;
return this_func(n-1) + this_func(n-2);
}
其中this_func 类似于类的this 指针,但用于函数。 [编辑:这可能仍然会受到this_func指针指向fib而不是记忆的fib的问题]
【问题讨论】:
-
我认为今天没有任何方法可以做到这一点,尤其是使用预编译的库。我在事后添加记忆的第一个猜测是使用链接器将 fib() 的重定位替换为 memoized_fib() 包装函数。但是,我不知道编译和链接阶段的详细信息,也不知道在链接阶段是否可以使用内部递归进行替换。哦,我也不知道有哪个链接器会进行这种替换。
-
如果您希望递归调用使用相同的缓存,我认为您需要以某种方式在它们之间共享缓存。也就是说,要么使用
static(更好,但更慢:thread_local)缓存或将缓存作为附加参数传递。无论哪种方式都需要修改fib。 (an example on wikipedia 使用后一种技术,通过函数的记忆版本作为参数传递缓存。)
标签: c++ c++11 recursion memoization