使用变量模板的递归计算-gcc vs clang [英] Recursive computation using variable templates - gcc vs clang

查看:86
本文介绍了使用变量模板的递归计算-gcc vs clang的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑下面的示例:

#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 5.x, 6.x, 7.x, 8.x, 9.x, and 10.x all print out 1 3 4 as a result.

    godbolt.org上的实时示例

    C语的行为令人惊讶。

    Clang's behavior is surprising.

    我缺少的C ++标准中的变量模板实例化,全局变量和递归之间是否存在微妙的交互作用?

    还是这是一个长期存在的Clang错误?

    顺便说一句,标记为 fib 作为 constexpr 解决了此问题( 在godbolt.org上 )。

    By the way, marking fib as constexpr solves the issue (on godbolt.org).

    推荐答案

    来自< a href = http://eel.is/c++draft/basic.start.dynamic#1 rel = nofollow noreferrer> [basic.start.dynamic] / 1 :


    具有静态存储持续时间的非局部变量的动态初始化是无序的(如果该变量是隐式或显式实例化的特殊化的话),如果该变量是部分有序的是一个内联变量,它不是隐式或显式实例化的专门化名称,否则是有序的。 [注:显式专门化的非内联静态数据成员或变量模板专门化已命令初始化。 —尾注]

    fib< 4> fib< 5> fib< 6> 是具有静态存储持续时间的非局部变量,它们是隐式实例化的专业知识,因此它们的动态初始化是无序的。

    fib<4>, fib<5> and fib<6> are non-local variables with static storage duration that are implicitly instantiated specializations, so their dynamic initialization is unordered.

    行为不是未定义的;必须有一些未指定的初始化顺序才能产生所看到的输出(每个 [ basic.start.dynamic] /3.3 (初始化顺序不确定)。实际上,clang按以下顺序初始化(请注意,动态初始化之前的变量具有静态初始化中的值0 ):

    The behavior is not undefined; there must be some some unspecified ordering of initialization that produces the output seen (per [basic.start.dynamic]/3.3 the initializations are indeterminately sequenced). In fact, clang initializes in the following order (noting that a variable before dynamic initialization has the value 0 from static initialization):

    fib<1> = 1 (actually static-initialized under [basic.start.static]/3)
    fib<2> = 1 (similarly)
    fib<4> = fib<2> + fib<3> = 1 + 0 = 1
    fib<3> = fib<1> + fib<2> = 1 + 1 = 2
    fib<5> = fib<3> + fib<4> = 2 + 1 = 3
    fib<6> = fib<4> + fib<5> = 1 + 3 = 4
    

    这与按顺序初始化的gcc(和MSVC)同等有效 fib< 3> fib< 4> fib< 5> fib< 6>

    This is equally as valid as gcc (and MSVC) initializating in the order fib<3>, fib<4>, fib<5>, fib<6>.

    这篇关于使用变量模板的递归计算-gcc vs clang的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆