不带初始值设定项的 constexpr 静态数据成员
constexpr static data member without initializer
#include <complex>
struct S
{
static std::complex<double> constexpr c;
};
GCC 生成错误,因为缺少初始值设定项。Clang 和 MSVC 不会生成错误。
据我所知,constexpr 静态数据成员必须有一个初始值设定项,即使它是类类型,具有可以在没有参数的情况下调用的构造函数(如本例所示(。不幸的是,我没有最新的C++标准来支持我的假设。
因此,正确的代码应该使用构造函数进行初始化,例如:
struct S
{
static std::complex<double> constexpr c {};
};
谁能证明哪个编译器是对的,哪个是错的?
GCC 是错误的。
GCC 对constexpr
变量使用 C++14 规则,这需要提供初始值设定项。这已根据 P0386 更改(粗体文本是新添加的文本(:
在 9.2.3.2p3 中,更改:
如果非易失性非内联const 静态数据成员是整型或枚举类型,则其在类定义中的声明可以指定 b种族或相等初始值设定项,其中作为赋值表达式的每个初始值设定项子句都是常量表达式(5.20(。
文本类型的静态数据成员可以使用 constexpr 说明符在类定义中声明;如果是这样,则其声明应指定一个大括号或等于初始值设定项,其中作为赋值表达式的每个初始值设定项子句都是常量表达式。[ 注意:在这两种情况下,成员都可能出现在常量表达式中。如果在程序中使用 (3.2( 的成员,则仍应在命名空间作用域中定义该成员,并且命名空间作用域定义不应包含初始值设定项。可以在类定义中定义内联静态数据成员,并且可以指定大括号或等于初始值设定项。如果使用 constexpr 说明符声明成员,则可以在没有初始值设定项的情况下在命名空间范围内重新声明该成员(此用法已弃用;请参阅 D.X(。其他静态数据成员的声明不应指定大括号或等于初始值设定项。
在这种特殊情况下,有两个答案:
- 对于 C++14,gcc是正确的(即 constexpr 静态数据成员必须有一个初始值设定项(。
- 对于 C++17 及以后的版本,gcc 是错误的,因为它拒绝编译一致性代码。
前一种情况 :在草案N3797(C++14(,9.4.2.3(静态数据成员([class.static.data](强调我的(:
可以在类中声明文本类型的
static
数据成员 使用constexpr
说明符进行定义;如果是这样,其声明应 指定一个大括号或等于初始值设定项,其中作为赋值表达式的每个初始值设定项子句都是一个常量表达式。
另请参阅:http://en.cppreference.com/w/cpp/language/static#Constant_static_members。
我说"在这种特殊情况下",因为std::complex
对double
有专门的LiteralType
。因此,上述规则适用。 对于一般(即非文字(类型,请参阅codekaizers答案。
后一种情况 :对于C++17,请参阅xskxzr的答案。
来自 dcl.constexpr#1:
使用
constexpr
说明符声明的函数或static
数据成员 隐式是inline
函数或变量
constexpr
static
数据成员隐式inline
。
同样来自class#static.data-3,强调我的:
inline
static
数据成员可以是 在class
定义中定义,并可能指定brace-or-equal-initializer
.
因此,海湾合作委员会是错误的。brace-or-equal-initializer
不是严格要求的。
编号 N4659 C++17 草案
- 添加静态constexpr成员是否会更改结构/类的内存映射
- 类内部和外部静态 constexpr 元组之间的差异
- 不带初始值设定项的 constexpr 静态数据成员
- 在类外部初始化的 constexpr 静态成员的声明中是否需要 constexpr 说明符
- 现在允许重新定义 constexpr 静态数据成员吗?(但不是内联常量)?
- 定义 constexpr 静态数据成员
- constexpr静态成员什么时候停止成为constexpr
- gcc 和 clang 中 constexpr 静态成员变量的链接器错误
- Constexpr静态成员函数用法
- constexpr静态结构类成员的声明冲突
- ConstexPR静态模板功能:G 错误是Clang上的警告
- 为什么调用此constexpr静态成员函数时不将其视为constexpr
- 为什么constexpr静态成员(类型为class)需要定义
- constexpr静态成员变量的异常行为
- constexpr 静态成员与变量
- 具有 constexpr 静态字符串会给出链接器错误
- 定义不同于 constexpr 静态成员的声明
- C++14 constexpr静态const std::数组初始化
- c++之前/之后的constexpr静态成员
- 完全专用模板的constexpr静态成员在CLang上的动态链接失败