我正在阅读有关C++模板的文章,并想对比一个函数的两种不同实现,该函数计算从0到N的和。
不幸的是,我有问题,我想通过例子来解决几个问题:
天真和代码:
#include <stdio.h>
template<int N>
struct Sum {
// Copied the implementation idea from Scott Meyers book
// "Effective C++". Is there a better way?
enum { value = N + Sum<N - 1>::value };
};
template<>
struct Sum<0> {
enum { value = 0 };
};
int main() {
// Works well in this case, but gives compilation error, if
// it's called with a larger value, such as 10000
// (error: template instantiation depth exceeds maximum of 900").
// How to improve the program properly, that it would
// not give compile time error?
printf("%dn", Sum<100>::value);
}
现在我的改进想法是使用一个累加器:
template<int Acc, int N>
struct Sum {
enum { value = Sum<Acc + N, N - 1>::value };
};
// Is that an appropriate way of writing the base case?
template<int Acc>
struct Sum<Acc, 0> {
enum { value = Acc };
};
然而,当在Ubuntu操作系统上使用简单的g++编译时:
int main() {
// Still gives the "depth exceeded" error.
printf("%dn", Sum<0, 1000>::value);
}
因此,我主要关心的是:
是否有任何现代c++编译器支持模板元编程?如果是,为这种优化编写代码的合适方式是什么
是否有任何现代c++编译器支持模板元编程的最后调用优化?如果是,为这种优化编写代码的合适方式是什么?
不,这没有道理。模板实例化不是函数调用最后/尾部调用优化与此处无关。与函数调用不同,模板实例化不是瞬态的,需要回收自动变量;相反,每个模板实例化都会成为编译器状态中的一个新类型。
模板元编程的全部意义在于,所有这些"调用"都将在程序之外进行优化;它们在构建过程中被"执行"。
这并没有改变这样一个事实,即在这个过程中,可以使用的递归数量有一个实现定义的限制。这是你达到的极限。
所以,不,没有"优化"来解决它。
简单回答:合并LCO不值得麻烦。
更长的解释:
C++模板元编程是图灵完备。理论上,可以在编译时仅使用模板计算任何可计算函数(如果给定足够的资源)。LCO将使这种计算更加高效。
这并不意味着模板应该用于复杂的计算。运行时间就是这样。C++模板只是帮助避免编写相同的代码。
事实上,不鼓励通过模板进行复杂的计算,因为它几乎没有编译器支持。预处理器只会将模板化的代码扩展成更多的代码,仅此而已。在处理模板时不会发生类型检查等。
因此,我认为c++的设计者有更多有趣的东西可以添加到语言中,而不是优化模板元编程。也许20年后我们会得到LCO的支持。目前没有