简体   繁体   English

g ++和clang ++使用静态成员的递归初始化的不同行为

[英]g++ and clang++ different behaviour with recursive initialization of a static member

Given the following code: 给出以下代码:

#include <iostream>

template <std::size_t N>
struct foo
 { static std::size_t value; };

template <>
std::size_t foo<0>::value = 0u;

template <size_t N>
std::size_t foo<N>::value = 1u + foo<N - 1u>::value;

int main()
 {
   std::cout
      << foo<3u>::value << ' '
      << foo<2u>::value << ' '
      << foo<1u>::value << ' '
      << foo<0u>::value << std::endl;
 }

where the static member value of the template struct foo is recursively initialized, I get different outputs from g++: 在递归初始化模板struct foo的静态成员value的地方,我从g ++获得不同的输出:

3 2 1 0

and from clang++: 从clang ++:

1 1 1 0

So seem that g++ initializes foo<N>::value recursively using the initialized value of foo<N-1u>::value where clang++ uses zero for foo<N-1u>::value . 所以似乎g ++使用foo<N-1u>::value的初始化foo<N>::value递归初始化foo<N-1u>::value ,其中clang ++对foo<N-1u>::value使用零。

Two questions: 两个问题:

  1. is the preceding code legit or is it Undefined Behavior in some way? 前面的代码是合法的还是以某种方式未定义的行为?
  2. if the preceding code is legit, who's right: g++ or clang++? 如果前面的代码是合法的,谁是对的:g ++或clang ++?

It is unspecified. 它没有具体说明。 Both compilers are right. 两个编译器都是对的。

Here are the relevant pieces from cppreference "initialization" . 以下是cppreference“initialization”的相关部分。

Static initialization 静态初始化

For all other non-local static and thread-local variables, Zero initialization takes place 对于所有其他非本地静态和线程局部变量,将进行零初始化

So for all these variables, they are zero when the program loads. 因此,对于所有这些变量,程序加载时它们为零。 Then: 然后:

Dynamic initialization 动态初始化

After all static initialization is completed , dynamic initialization of non-local variables occurs in the following situations: 完成所有静态初始化后 ,在以下情况下会发生非局部变量的动态初始化:

1) Unordered dynamic initialization, which applies only to (static/thread-local) class template static data members and ... that aren't explicitly specialized. 1)无序动态初始化,仅适用于(静态/线程局部)类模板静态数据成员和......未明确专门化的。

And these variables match the criteria. 这些变量符合标准。 And then it says: 然后它说:

Initialization of such static variables is indeterminately sequenced with respect to all other dynamic initialization .... 对于所有其他动态初始化,这些静态变量的初始化是不确定的。

Which means that any sequence of initialization is fine. 这意味着任何初始化序列都可以。 Both compilers are correct. 这两种编译器是正确的。

To avoid the issue use constexpr to force a "constant initialization" instead. 为避免此问题,请使用constexpr强制执行“常量初始化”。

It is Unspecified . 它是未指定的

You are using a construct where you reference a variable definition onto itself - perhaps somewhat analogue to saying int i = i-1 . 您正在使用一个构造 ,您可以在其中引用变量定义 - 可能有点类似于说int i = i-1 In clang case, it is just using the generic template definition 在clang的情况下,它只是使用通用模板定义

template <std::size_t N>
struct foo
  { static std::size_t value; };//without specialization this will be ZERO initialized

because it hasn't seen 'itself' like normal template class or function would (as opposed to gcc case). 因为它没有像普通模板类或函数那样看到 '本身'(与gcc情况相反)。

To sum up: 总结一下:

1) Legit 1)合法

2) Unspecified 2)未指定

To avoid issues use and specialize the class template instead. 为了避免问题,请使用并专门化类模板。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 g++ 和 clang++ 在列表初始化时给出不同的结果 - g++ and clang++ give different results on list initialization g ++和clang ++使用变量模板和SFINAE的不同行为 - g++ and clang++ different behaviour with variable template and SFINAE g ++和clang ++使用运算符&lt;()重载的不同行为 - g++ and clang++ different behaviour with operator<() overloading g ++和clang ++使用指向可变参数模板函数的指针的不同行为 - g++ and clang++ different behaviour with pointer to variadic template functions g ++和clang ++使用自动参数的模板特化的不同行为 - g++ and clang++ different behaviour with template specialization for auto argument g++ 和 clang++ 与可变参数容器的不同行为 - g++ and clang++ different behaviour with variadic container 带有集成模板参数的g ++和clang ++不同的行为 - g++ and clang++ different behaviour with integral template parameter g ++和clang ++与流输入和无符号整数的不同行为 - g++ and clang++ different behaviour with stream input and unsigned integer g ++和clang ++与SFINAE和SFINAE失败的不同行为 - g++ and clang++ different behaviour with SFINAE and SFINAE failure C++20 成员初始化列表 Clang++ vs G++ - C++20 Member Initialization List Clang++ vs G++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM