#include <complex>
struct S
{
static std::complex<double> constexpr c;
};
gcc生成错误,因为缺少初始化程序。 Clang和MSVC不会产生错误。
据我所知,constexpr静态数据成员必须有一个初始化程序,即使它是类型类型,具有可以不带参数调用的构造函数(如本例所示)。不幸的是,我没有最新的C ++标准来支持我的假设。
所以正确的代码应该用构造函数初始化,例如:
struct S
{
static std::complex<double> constexpr c {};
};
任何人都可以证明哪个编译器是正确的,哪个是错的?
答案 0 :(得分:7)
GCC对constexpr
变量使用C ++ 14规则,这需要提供初始值设定项。这是根据P0386更改的(粗体文本是新添加的文字):
在9.2.3.2p3中,更改:
如果非易失性 n on-inline const静态数据成员是整数或枚举类型,则其在类定义中的声明可以指定ab race-or-equal -initializer ,其中 assignment-expression 的每个 initializer-clause 是一个常量表达式(5.20)。
可以使用constexpr说明符在类定义中声明文字类型的静态数据成员;如果是这样,它的声明应指定一个大括号或等于初始化器,其中作为赋值表达式的每个initializer子句都是一个常量表达式。 [注意:在这两种情况下,成员可能会出现在常量表达式中。 - 结束注释]如果程序中使用了odr-used(3.2),并且命名空间作用域定义不包含初始值设定项,则仍应在命名空间作用域中定义该成员。 A n inline静态数据成员可以在类定义中定义,并可以指定 b race-or-equal-initializer 。如果使用constexpr说明符声明成员,则可以在命名空间范围内重新声明它没有初始化程序(此用法已弃用;请参阅DX)。其他静态数据成员的声明不应指定 b race-or-equal-initializer 。
答案 1 :(得分:4)
在这个特殊情况下,有两个答案:
以前的案例 :草稿N3797(C ++ 14 ),9.4.2.3(静态数据成员)[类。 static.data](强调我的):
可以在类中声明文字类型的
static
数据成员 使用constexpr
说明符定义;如果是,其声明应 指定大括号或等于初始化 ,其中每个 initializer-clause 这是一个赋值表达式是一个常量表达式。
另请参阅:http://en.cppreference.com/w/cpp/language/static#Constant_static_members。
我在特定的案例&#34;中说过&#34;因为std::complex
has a specialization for double
是LiteralType
。因此上述规则适用。
对于一般(即非文字)类型,请参阅codekaizers answer。
后一种情况 :对于C ++ 17 ,请参阅xskxzr's answer。
答案 2 :(得分:1)
使用
static
说明符声明的函数或constexpr
数据成员 隐式地是inline
函数或变量
constexpr
static
个数据成员隐含inline
同样来自class#static.data-3,强调我的:
inline
static
数据成员可能是 在class
定义中定义,可以指定brace-or-equal-initializer
。
因此,海湾合作委员会是错误的。 brace-or-equal-initializer
严格要求。
参考:N4659 C ++ 17草案