c++支持模板元编程中的最后调用优化



我正在阅读有关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的支持。目前没有

最新更新