是否在constexpr静态成员的声明中需要constexpr说明符在类外部初始化?

时间:2018-05-21 00:43:34

标签: c++ c++11 language-lawyer c++17 constexpr

C ++17§10.1.5/ 1 陈述:

  

constexpr说明符仅适用于a的定义   变量或变量模板或函数或的声明   功能模板。使用。声明的函数或静态数据成员   constexpr说明符隐式地是内联函数或变量   (10.1.6)。如果函数或函数模板的任何声明都有   constexpr说明符,然后它的所有声明都应包含   constexpr说明符。

a comment by Richard Smith引用的C ++ 11(§7.1.5/ 1)以来,标准中存在类似的段落,其中他认为C ++标准要求constexpr说明符匹配变量的声明定义。上段显式的最后一个陈述要求constexpr说明符匹配函数和函数模板声明,但提及变量声明。

§10.1.5/ 9 陈述:

  

对象声明中使用的constexpr说明符声明了   对象为const。这样的物体应具有字面类型,并且应为   初始化。在任何constexpr变量声明中,   初始化的初始化应该是一个常量表达式   (8.20)。

当然,如果我们有一个单独的声明和定义,它们都需要匹配const,无论constexpr说明符是否需要匹配。

§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`

虽然I have been told that this is wrong支持GCC,Clang和MSVC支持对constexpr使用静态数据成员的这种解释。

在变量声明和定义中使用constexpr说明符的不匹配是否违规?

如果这实际上是违规,则无法正确定义其自己类的constexpr静态数据成员,因为类内定义是禁止的,因为类型不完整且属于类外如果类内声明用constexpr说明符标记,则禁止定义包含初始值。

1 个答案:

答案 0 :(得分:1)

如果我读这个:

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完成,其0的常量值为_value
这会调用您的constexpr constructor

constexpr S(int value = {}) : _value{ value } {}

根据basic.start.static - 常量初始化

  

变量或临时对象o常量初始值设定项是   初始化程序,其完整表达式是常量表达式,除了   如果o是一个对象,这样的初始值设定项也可以调用    constexpr构造函数用于o及其子对象,即使这些对象属于非文字类类型。

AND expr.const/8.7 - 常量评估

  

一个变量,其名称显示为可能的常量计算值   表达式是 constexpr变量或非易失性   const限定的整数类型或引用类型。

因此:

  

使用constexpr说明符不匹配是违法行为吗?   跨变量声明和定义?

我相信你的代码很好。