没有初始化程序的constexpr静态数据成员

时间:2018-06-01 07:17:54

标签: c++ gcc visual-c++ clang language-lawyer

#include <complex>

struct S
{
  static std::complex<double> constexpr c;
};

gcc生成错误,因为缺少初始化程序。 Clang和MSVC不会产生错误。

据我所知,constexpr静态数据成员必须有一个初始化程序,即使它是类型类型,具有可以不带参数调用的构造函数(如本例所示)。不幸的是,我没有最新的C ++标准来支持我的假设。

所以正确的代码应该用构造函数初始化,例如:

struct S
{
  static std::complex<double> constexpr c {};
};

任何人都可以证明哪个编译器是正确的,哪个是错的?

3 个答案:

答案 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)

在这个特殊情况下,有两个答案:

  • 对于C ++ 14,gcc 正确(即constexpr静态数据成员必须具有初始化程序)。
  • 对于C ++ 17及更高版本,gcc 错误,因为它拒绝编译符合规范的代码。

以前的案例 :草稿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 doubleLiteralType。因此上述规则适用。 对于一般(即非文字)类型,请参阅codekaizers answer

后一种情况 :对于C ++ 17 ,请参阅xskxzr's answer

答案 2 :(得分:1)

来自dcl.constexpr#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草案