简体   繁体   English

现在允许重新定义constexpr静态数据成员吗? (但不是内联常量)?

[英]Redefinitions of constexpr static data members are allowed now? (but not inline const)?

The following fails to compile under both gcc and clang in c++14, but succeeds with c++1z: 以下无法在c ++ 14中的gcc和clang下编译,但是使用c ++ 1z成功:

struct Cls {
  static constexpr int N = 0;
};
constexpr int Cls::N;
constexpr int Cls::N;

The C++14 error is predictable: redefinition of 'constexpr const int Cls::N' C ++ 14错误是可预测的: redefinition of 'constexpr const int Cls::N'

What changed to make this legal? 是什么改变使这合法? I found: 我发现:

n4659 10.1.5 [dcl.constexpr] n4659 10.1.5 [dcl.constexpr]

A function or static data member declared with the constexpr specifier is implicitly an inline function or variable 使用constexpr说明符声明的函数或静态数据成员隐式地是内联函数或变量

So I thought it might have to do with inline variables, but the following fails for c++1z under both compilers 所以我认为它可能与内联变量有关,但是在两个编译器下c ++ 1z的后续失败

struct Cls {
  static inline const int N = 0;
};
inline const int Cls::N; // note, only one definition here

Before C++17, you needed to re-declare all static variables outside the class in exactly one translation unit (typically each translation unit is a .cpp file and vice versa, but this isn't required). 在C ++ 17之前,您需要在一个转换单元中重新声明类外的所有static变量(通常每个转换单元都是.cpp文件,反之亦然,但这不是必需的)。 As you pointed out, C++17 introduces inline class member variables, and static constexpr variables automatically qualify. 正如您所指出的,C ++ 17引入了inline类成员变量, static constexpr变量自动符合条件。 You are not allowed to redeclare inline variables outside the class, as you saw in your second example, but an exception was made for constexpr because previously you were allowed (and in fact required) to do so, but the syntax is deprecated. 不允许再声明inline在类的外部变量,正如你在第二个例子中看到的,但一个例外是由constexpr因为以前你被允许(在需要的事实)这样做,但语法已过时。

In [class.static.data]p2, it allows that syntax for non-inline members (“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.”) 在[class.static.data] p2中,它允许非内联成员的语法(“在其类定义中声明非内联静态数据成员不是定义,并且可能是除了cv void之外的不完整类型。未在类定义中内联定义的静态数据成员的定义应出现在包含成员类定义的命名空间范围内。“)

In the next paragraph, the standard allows constexpr outside-of-class declarations and requires them for non- constexpr data (emphasis added): 在下一段中,该标准允许constexpr类外声明,并要求它们用于非constexpr数据(强调添加):

If a non-volatile non-inline const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression (8.20). 如果非易失性非内联const静态数据成员是整数或枚举类型,则它在类定义中的声明可以指定一个大括号或大小为初始化器 ,其中作为赋值表达式的每个initializer子句都是一个常量表达式(8.20)。 The member shall still be defined in a namespace scope if it is odr-used (6.2) in the program and the namespace scope definition shall not contain an initializer . 如果在程序中使用odr-used(6.2),并且命名空间作用域定义不包含初始值设定项,则仍应在命名空间作用域中定义该成员。 An inline static data member may be defined in the class definition and may specify a brace-or-equal-initializer . 可以在类定义中定义内联静态数据成员,并且可以指定大括号或等于初始化器 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). 如果使用constexpr说明符声明成员,则可以在没有初始化程序的命名空间作用域中重新声明该成员 (不推荐使用此用法;请参阅D.1)。 Declarations of other static data members shall not specify a brace-or-equal-initializer . 其他静态数据成员的声明不应指定大括号或等于初始化器

And here's the deprecation note, D.1 Redeclaration of static constexpr data members [depr.static_constexpr]: 这里是弃用说明,D.1静态constexpr数据成员的重新声明[depr.static_constexpr]:

For compatibility with prior C++ International Standards, a constexpr static data member may be redundantly redeclared outside the class with no initializer. 为了与先前的C ++国际标准兼容,可以在类外部冗余地重新声明constexpr静态数据成员而不使用初始化程序。 This usage is deprecated. 不推荐使用此用法。 [ Example: [ 例如:

 struct A { static constexpr int n = 5; // definition (declaration in C++ 2014) }; constexpr int A::n; // redundant declaration (definition in C++ 2014) 

— end example ] - 结束例子 ]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM