编译器是否保证优化模板生成的递归代码?

时间:2013-10-04 19:42:39

标签: c++ templates optimization c++11 recursion

Bjarne Stroustrup的C++11 FAQ about templates包含以下词语:

  

这是在编译时完成的标准函数式编程。

这是否意味着his example with printf在编译后应该是递归的节点?我简化了一些示例,所有具有禁用优化的编译器都会生成递归代码。例如,这里是the output from g++ -O2,它不是递归的,但是无论如何,clang都会保持递归。

我错过了什么?

P.S。我的错误。在这个示例中,具有优化选项的clang编译代码与所有其他代码一样 - 以简单的方式(无递归)。但是没有优化 - 所有仍然使用递归进行编译。

2 个答案:

答案 0 :(得分:3)

Bjarne关于编译时递归的评论指的是评估模板的方式,而不是生成的代码的工作方式。例如,请考虑以下模板:

template <typename... Args> struct Length;
template <> struct Length<> {
    static const size_t value = 0;
};
template <typename First, typename... Rest> struct Length {
    static const size_t value = 1 + Length<Rest>::value;
};

在这里,如果我们实例化Length<int, int, int, int>那么

  • Length<int, int, int, int>实例化
  • Length<int, int, int>,实例化
  • Length<int, int>,实例化
  • Length<int>,实例化
  • Length<>

这个过程是Bjarne所指的模板的纯函数式递归扩展。这是扩展模板以生成代码的过程,该代码是在编译时递归完成的,而不是在编译器中展开的实际生成的代码。只要不改变代码的基本含义,C ++编译器就可以自由地优化代码,但它认为合适。如果你有一个使用这种编译时递归方式的递归函数,编译器可能优化它,但不能保证它会。 C ++标准对允许或不允许的哪种优化没有任何限制,只是描述了所需的行为,因此没有相关的规则。

希望这有帮助!

答案 1 :(得分:1)

仅仅因为他说“这是在编译时完成的标准函数式编程”并不意味着生成的结果代码在运行时完全是非递归的。他的陈述根本没有提到运行时间。

没有提到编译器应该在运行时生成什么。消除可变参数模板函数递归的唯一方法是对所有递归调用进行内联,尾调用优化和/或编译器以某种方式将代码重新排列为循环。所以这完全取决于编译器。