是否在类外部初始化了constexpr静态成员的声明时需要的constexpr说明符? [英] Is the constexpr specifier required on the declaration of a constexpr static member initialized outside of the class?

查看:180
本文介绍了是否在类外部初始化了constexpr静态成员的声明时需要的constexpr说明符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++ 17§10.1.5/1 声明:

constexpr说明符应仅应用于 变量或变量模板或函数的声明或 功能模板.用声明的函数或静态数据成员 constexpr说明符隐式是一个内联函数或变量 (10.1.6).如果函数或函数模板的任何声明具有 constexpr说明符,则其所有声明应包含 constexpr说明符.

The constexpr specifier shall be applied only to the definition of a variable or variable template or the declaration of a function or function template. A function or static data member declared with the constexpr specifier is implicitly an inline function or variable (10.1.6). If any declaration of a function or function template has a constexpr specifier, then all its declarations shall contain the constexpr specifier.

自C ++ 11(第7.1.5/1节)以来,该标准中已有类似的段落,在

A similar paragraph has existed in the standard since C++11 (§7.1.5/1), which is cited in a comment by Richard Smith, in which he contends that the C++ Standard does not require the constexpr specifier to match between the declaration and definition of a variable. The last statement of the above paragraph explicitly requires the constexpr specifier to match across function and function template declarations, but does not mention variable declarations.

§10.1.5/9 声明:

在对象声明中使用的constexpr说明符声明 对象为const.此类对象应具有文字类型,并且应为 初始化.在任何constexpr变量声明中, 初始化的完整表达式应为常量表达式 (8.20).

A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. In any constexpr variable declaration, the full-expression of the initialization shall be a constant expression (8.20).

当然,如果我们有单独的声明和定义,则无论是否需要匹配constexpr说明符,它们都必须在const ness中进行匹配.

Of course if we have a separate declaration and definition, they will both need to match in constness, regardless of whether the constexpr specifiers are required to match.

§12.2.3.2/2-3 说:

2在其类中声明非内联静态数据成员 定义不是定义,可能是不完整的类型 比 cv void.静态数据成员的定义不是 类定义中的内联定义应出现在名称空间中 包含成员的班级定义的范围.在定义中 在名称空间范围内,静态数据成员的名称应为合格的 使用::运算符通过其类名来表示. initializer 表达式 静态数据成员的定义在其类的范围内 (6.3.7).

2 The declaration of a non-inline static data member in its class definition is not a definition and may be of an incomplete type other than cv void. The definition for a static data member that is not defined inline in the class definition shall appear in a namespace scope enclosing the member’s class definition. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the :: operator. The initializer expression in the definition of a static data member is in the scope of its class (6.3.7).

3如果非易失性非内联const静态数据成员属于 整数或枚举类型...如果用 constexpr说明符,它可以在命名空间范围内重新声明而没有 初始化程序(不建议使用此用法;请参见D.1).其他声明 静态数据成员不得指定
brace-or-equal-initializer .

3 If a non-volatile non-inline const static data member is of integral or enumeration type... If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see D.1). Declarations of other static data members shall not specify a brace-or-equal-initializer.

§D.1/1 内容为:

为与先前的C ++国际标准兼容,请constexpr 静态数据成员可以在类外重复声明 没有初始化程序.不建议使用此用法.

For compatibility with prior C++ International Standards, a constexpr static data member may be redundantly redeclared outside the class with no initializer. This usage is deprecated.

我们可以从中收集到,如果使用constexpr说明符对成员进行了声明,则名称空间范围 definition 是多余的,而 initializer 表达式必须与 declaration 配对,并且必须从 definition / redeclaration 中省略.

From which we can gather that if the member is declared with the constexpr specifier, then a namespace scope definition is redundant and the initializer expression must be paired with the declaration and must be omitted from the definition/redeclaration.

作为一个完整的示例,我提供了其自己的文字类型类的静态成员的情况(不能在类中初始化):

To serve as a complete example, I offer up the case of a static member of its own literal type class (which cannot be initialized in-class):

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说明符是否违反?

Is it a violation to have non-matching use of the constexpr specifier across variable declarations and definitions?

如果这实际上是违反的,则不可能正确定义其自己类的constexpr静态数据成员,因为禁止使用类内定义,因为类型不完整且类外定义为如果在类声明中用constexpr说明符标记,则禁止包含初始化程序.

If this is in fact a violation, then it is impossible to correctly define a constexpr static data member of its own class, as in-class definitions are prohibited because the type is incomplete and out-of-class definitions are prohibited from including an initializer if the in-class declaration is marked with the constexpr specifier.

推荐答案

如果我要阅读以下内容:

If I were to read this:

static S const ZERO; // not marked `constexpr`, but still `const`

S::ZERO永远不会由于const而在运行时更改其值.

S::ZERO will never change its value during run-time due to const.

但是:

constexpr S S::ZERO{ 0 }; // implicitly `inline` (if C++17) and `const`

S::ZERO执行

Constant Evaluation,对于_value将具有恒定的整数值0.
这会调用您的constexpr constructor:

Constant Evaluation is done for S::ZERO which will have constant integral value 0 for _value.
This invokes your constexpr constructor:

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

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

变量或临时对象o常量初始化程序是一个 完整表达式为常量表达式的初始化程序,除了 如果o是一个对象,则此类初始化程序也可能会调用 o及其子对象的 constexpr构造函数,即使这些对象属于非文字类类型.

A constant initializer for a variable or temporary object o is an initializer whose full-expression is a constant expression, except that if o is an object, such an initializer may also invoke constexpr constructors for o and its subobjects even if those objects are of non-literal class types.

AND expr.const/8.7 -恒定评估:

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

a variable whose name appears as a potentially constant evaluated expression that is either a constexpr variable or is of non-volatile const-qualified integral type or of reference type.

因此:

对constexpr说明符进行不匹配的使用是否违规 跨变量声明和定义?

Is it a violation to have non-matching use of the constexpr specifier across variable declarations and definitions?

我相信您的代码很好.

这篇关于是否在类外部初始化了constexpr静态成员的声明时需要的constexpr说明符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆