g++ 和 clang++ 静态成员递归初始化的不同行为
g++ and clang++ different behaviour with recursive initialization of a static member
给定以下代码:
#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;
}
递归初始化模板结构 foo
的静态成员 value
,我从 g++ 得到不同的输出:
3 2 1 0
来自 clang++:
1 1 1 0
看来 g++ 使用 foo<N-1u>::value
的初始化值递归初始化 foo<N>::value
,其中 clang++ 使用零表示 foo<N-1u>::value
。
两个问题:
- 前面的代码是合法的还是在某种程度上是未定义的行为?
- 如果前面的代码是合法的,谁是对的:g++ 还是 clang++?
未指定。两个编译器都是对的。
以下是 cppreference "initialization".
的相关文章
静态初始化
For all other non-local static and thread-local variables, Zero initialization takes place
所以对于所有这些变量,它们在程序加载时都为零。那么:
动态初始化
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.
并且这些变量符合标准。然后它说:
Initialization of such static variables is indeterminately sequenced
with respect to all other dynamic initialization ....
这意味着任何初始化顺序都可以。两个编译器都是正确的。
为避免此问题,请使用 constexpr
来强制使用 "constant initialization"。
未指定。
您正在使用 构造,您在其中将变量定义引用到自身 - 也许有点类似于说 int i = i-1
。在 clang 情况下,它只是使用通用模板定义
template <std::size_t N>
struct foo
{ static std::size_t value; };//without specialization this will be ZERO initialized
因为它还没有 见过 'itself' 像普通模板 class 或函数那样(与 gcc 案例相反)。
总结一下:
1) 合法
2) 未指定
为避免出现问题,请使用 constexpr 并专门化 class 模板。
给定以下代码:
#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;
}
递归初始化模板结构 foo
的静态成员 value
,我从 g++ 得到不同的输出:
3 2 1 0
来自 clang++:
1 1 1 0
看来 g++ 使用 foo<N-1u>::value
的初始化值递归初始化 foo<N>::value
,其中 clang++ 使用零表示 foo<N-1u>::value
。
两个问题:
- 前面的代码是合法的还是在某种程度上是未定义的行为?
- 如果前面的代码是合法的,谁是对的:g++ 还是 clang++?
未指定。两个编译器都是对的。
以下是 cppreference "initialization".
的相关文章静态初始化
For all other non-local static and thread-local variables, Zero initialization takes place
所以对于所有这些变量,它们在程序加载时都为零。那么:
动态初始化
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.
并且这些变量符合标准。然后它说:
Initialization of such static variables is indeterminately sequenced with respect to all other dynamic initialization ....
这意味着任何初始化顺序都可以。两个编译器都是正确的。
为避免此问题,请使用 constexpr
来强制使用 "constant initialization"。
未指定。
您正在使用 构造,您在其中将变量定义引用到自身 - 也许有点类似于说 int i = i-1
。在 clang 情况下,它只是使用通用模板定义
template <std::size_t N>
struct foo
{ static std::size_t value; };//without specialization this will be ZERO initialized
因为它还没有 见过 'itself' 像普通模板 class 或函数那样(与 gcc 案例相反)。
总结一下:
1) 合法
2) 未指定
为避免出现问题,请使用 constexpr 并专门化 class 模板。