C++17§10.1.5/1声明:
constexpr说明符只适用于变量或变量模板的定义或函数或函数模板的声明。使用constexpr说明符声明的函数或静态数据成员隐含为内联函数或变量(10.1.6)。如果函数或函数模板的任何声明都有constexpr说明符,则其所有声明都应包含constexpr说明符。
自C++11 (§7.1.5/1)以来,标准中也有类似的一段,他在理查德·史密斯的评论中引用了这一段落,他在该段落中认为,“C++标准做而不是”要求constexpr说明符在变量的声明和定义之间进行匹配。上一段的最后一条语句显式地要求constexpr说明符在函数和函数模板声明之间进行匹配,但是没有提到变量声明。
§10.1.5/9声明:
对象声明中使用的
constexpr说明符将对象声明为const。这类对象应具有文字类型,并应初始化。在任何constexpr变量声明中,初始化的完整表达式应该是一个常量表达式(8.20)。
当然,如果我们有单独的声明和定义,那么无论constexpr说明符是否需要匹配,它们都需要在constexprness中匹配。
§12.2.3.2/2-3说:
2非内联静态数据成员在其类定义中的声明不是定义,可能是cv
void以外的不完整类型。未在类定义中内联定义的静态数据成员的定义应出现在包含该成员的类定义的命名空间范围中。在命名空间范围的定义中,静态数据成员的名称应使用::操作符按其类名限定。静态数据成员定义中的初始化器表达式位于其类(6.3.7)的范围内。 3非易失性、非内联const静态数据成员为整数型或枚举型.如果成员是用constexpr说明符声明的,则可以在没有初始化器的命名空间范围内重新声明该成员(不推荐这种用法;请参见D.1)。其他静态数据成员的声明不应指定大括号或等初始化器。
§D.1/1如下:
为了与以前的C++国际标准兼容,
constexpr静态数据成员可以在类之外冗余地重新声明,而不需要初始化器。这种用法是不可取的。
由此我们可以收集到,如果成员是用constexpr说明符声明的,那么名称空间范围定义是多余的,初始化器表达式必须与声明配对,并且必须从定义/重声明中省略。
作为一个完整的示例,我提供了它自己的文字类型类的静态成员的情况(不能在类中初始化):
struct S
{
static S const ZERO; // not marked `constexpr`, but still `const`
constexpr S(int value = {}) : _value{ value } {}
int const _value;
};
constexpr S S::ZERO{ 0 }; // implicitly `inline` (if C++17) and `const`这种对静态数据成员使用constexpr的解释得到了GCC、Clang和MSVC (通过有人告诉我这是不对的 )的支持。
在变量声明和定义之间不匹配地使用constexpr说明符是违反的吗?
如果这实际上是违反的,那么就不可能正确地定义自己类的constexpr静态数据成员,因为类中的定义是被禁止的,因为类型是不完整的,如果类内声明被标记为constexpr说明符,则禁止类外定义包含初始化器。
发布于 2018-05-21 01:55:48
如果我读到这个:
static S const ZERO; // not marked `constexpr`, but still `const`S::ZERO在运行时不会因为const而改变它的值。
然而:
constexpr S S::ZERO{ 0 }; // implicitly `inline` (if C++17) and `const`Constant Evaluation是针对S::ZERO做的,_value的积分值为0。
这会调用您的constexpr constructor
constexpr S(int value = {}) : _value{ value } {}按照basic.start.static -常量初始化
变量或临时对象
o的常量初始化器是其全部表达式为常量表达式的初始化器,但如果o是对象,则即使这些对象是非文字类类型的对象,此类初始化器也可能调用o及其子对象的constexpr构造函数。
和expr.const/8.7 -常数评估
一个变量,其名称显示为一个潜在的常量求值表达式,该表达式要么是constexpr变量,要么是非易失性const限定的积分类型,或者是引用类型。
因此:
在变量声明和定义之间不匹配地使用constexpr说明符是违反的吗?
我相信你的密码没问题。
https://stackoverflow.com/questions/50440671
复制相似问题