【发布时间】:2020-06-06 16:47:41
【问题描述】:
考虑以下示例:
#include <cstdio>
template <int N>
int fib = fib<N - 1> + fib<N - 2>;
template <> int fib<2> = 1;
template <> int fib<1> = 1;
int main()
{
std::printf("%d %d %d", fib<4>, fib<5>, fib<6>);
}
GCC 7.x、8.x、9.x 和 10.x 都打印出
3 5 8的预期结果。Clang 5.x、6.x、7.x、8.x、9.x 和 10.x 都会因此打印出
1 3 4。
Clang 的行为令人惊讶。
我所缺少的 C++ 标准中的变量模板实例化、全局变量和递归之间是否存在任何微妙的交互?
或者这是一个长期存在的 Clang 错误?
顺便说一句,将fib 标记为constexpr 可以解决问题(on godbolt.org)。
【问题讨论】:
-
我的直觉说这是静态初始化命令的失败......在这种情况下它是否被标准中的某些东西允许或者它是一个 Clang 错误,我不确定。但是
constexpr修复它是有意义的,因为它在概念上强加了一个排序。 -
@cdhowie 当它们以错误的顺序初始化时会不会导致无限递归?
-
@idclev463035818 否。问题是,当实例化
fib<4>导致fib<3>被实例化时,标准保证fib<3>在fib<4>之前初始化?如果不是,fib<4>在初始化之前使用它并读取一个不确定的值。 -
仅供参考,
clang-cl给出了这个(三次,每个实例一次):警告:声明需要全局构造函数 [-Wglobal-constructors] -
@cdhowie 你能用单个编译单元搞定静态初始化命令吗?
标签: c++ recursion c++14 language-lawyer variable-templates