zjy*_*qs 7 c++ language-lawyer c++17 c++20
对于模板类,
template <typename T>
struct Test {
T data;
static const Test constant;
};
Run Code Online (Sandbox Code Playgroud)
定义特殊类型的成员变量时没问题static constexpr:
template <>
inline constexpr Test<int> Test<int>::constant {42};
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/o4c4YojMf
static constexpr当直接从模板类定义成员而不实例化时,编译器的结果会有所不同:
template <typename T>
inline constexpr Test<T> Test<T>::constant {42};
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/M8jdx3WzM
GCC编译。
clang忽略constexpr定义中的说明符。
MSVC.../std:c++17效果很好,但/std:c++20由于重新定义而被拒绝。
在这个例子中,哪一个是正确的?为什么?
我认为 GCC接受给定示例是正确的。这是因为static指定的数据成员constant是一个普通的数据成员变量(尽管它仍然被视为模板化实体)。
由于constant是一个普通的数据成员变量,因此dcl.constexpr#1.sentence-1适用于它:
constexpr 说明符仅应用于变量或变量模板的定义或者函数或函数模板的声明。
(强调我的)
因此,由于您在类模板之后提供的构造只不过是普通静态数据成员的类外定义constant,因此给定的示例格式良好。
template <typename T>
constexpr Test<T> Test<T>::constant {42}; //this is an out-of-class definition for the ordinary static data member variable `constant`
Run Code Online (Sandbox Code Playgroud)
请注意,dcl.constexpr#1.sentence-1没有提到模板化实体,而只提到“变量”和“变量模板”,并且由于constant是一个变量(普通),因此同样应该适用于constant.