以下在c++14的gcc和clang下都编译失败,但是用c++1z编译成功:
struct Cls {
static constexpr int N = 0;
};
constexpr int Cls::N;
constexpr int Cls::N;
C++14 错误是可以预见的:redefinition of ‘constexpr const int Cls::N’
什么改变使这合法?我发现:
n4659 10.1.5 [dcl.constexpr]
A function or static data member declared with the constexpr specifier is implicitly an inline function or variable
所以我认为这可能与内联变量有关,但以下两种编译器下的 c++1z 都失败了
struct Cls {
static inline const int N = 0;
};
inline const int Cls::N; // note, only one definition here
最佳答案
在 C++17 之前,您需要在一个翻译单元中重新声明类外的所有 static
变量(通常每个翻译单元都是一个 .cpp
文件反之亦然,但这不是必需的)。正如您所指出的,C++17 引入了 inline
类成员变量,并且 static constexpr
变量自动限定。正如您在第二个示例中看到的那样,您不允许在类外部重新声明 inline
变量,但是 constexpr
出现了异常,因为之前你被允许(实际上是被要求)这样做,但语法已被弃用。
在 [class.static.data]p2 中,它允许非内联成员的语法(“在其类定义中声明非内联静态数据成员不是定义,可能是 cv void 以外的不完整类型。未内联定义的静态数据成员的定义 在类定义中应出现在包含成员类定义的命名空间范围内。”)
在下一段中,该标准允许 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). 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. 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 theconstexpr
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 重新声明静态 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. 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 ]
关于c++ - 现在允许重新定义 constexpr 静态数据成员吗? (但不是内联常量)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45019980/