x y*_*x y 15 c++ gcc clang visual-c++ language-lawyer
#include <complex>
struct S
{
static std::complex<double> constexpr c;
};
Run Code Online (Sandbox Code Playgroud)
gcc生成错误,因为缺少初始化程序.Clang和MSVC不会生成错误.
据我所知,constexpr静态数据成员必须有一个初始化程序,即使它是具有可以不带参数调用的构造函数的类类型(如本例所示).不幸的是,我没有最新的C++标准来支持我的假设.
所以正确的代码应该用构造函数初始化,例如:
struct S
{
static std::complex<double> constexpr c {};
};
Run Code Online (Sandbox Code Playgroud)
任何人都可以证明哪个编译器是正确的,哪个是错的?
GCC错了.
GCC对constexpr变量使用C++ 14规则,这需要提供初始化程序.这是根据P0386更改的(粗体文本是新添加的文本):
在9.2.3.2p3中,更改:
如果非易失性上直列Ñ const的静态数据成员是整型或枚举类型的,其在类定义声明可以指定AB 种族或相等的初始值设定,其中每个初始化子句,其为赋值表达式是一个常量表达式(5.20).
可以使用constexpr说明符在类定义中声明文字类型的静态数据成员; 如果是这样,它的声明应指定一个大括号或等于初始化器,其中作为赋值表达式的每个initializer子句都是一个常量表达式.[注意:在这两种情况下,成员可能会出现在常量表达式中. - 结束说明]该成员仍然在命名空间范围来限定,如果它是在程序ODR使用(3.2)和命名空间范围定义不应含有一个初始化.A N管线内静态数据成员可以在类定义来定义,并且可以指定一个b race-or-equal-initializer.如果使用constexpr说明符声明该成员,则可以在没有初始化程序的命名空间范围内重新声明它(不推荐使用此用法;请参阅DX).其他静态数据成员的声明不应指定b race-or-equal-initializer.
在这种特殊情况下,有两个答案:
前案例:在草案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 answer。
后一种情况:对于 C++ 17,请参阅xskxzr 的回答。
| 归档时间: |
|
| 查看次数: |
1193 次 |
| 最近记录: |