现在可以重新定义constexpr静态数据成员了吗? (但不是内联const)? [英] Redefinitions of constexpr static data members are allowed now? (but not inline const)?

查看:100
本文介绍了现在可以重新定义constexpr静态数据成员了吗? (但不是内联const)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下在c ++ 14中的gcc和clang下均无法编译,但在c ++ 1z中成功:

The following fails to compile under both gcc and clang in c++14, but succeeds with c++1z:

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

C ++ 14错误是可预测的:'constexpr const int的定义Cls :: N'

The C++14 error is predictable: redefinition of ‘constexpr const int Cls::N’

为了使此法律合法而进行了哪些更改?我发现:

What changed to make this legal? I found:


n4659 10.1.5 [dcl.constexpr]

用constexpr
说明符声明的函数或静态数据成员隐式是内联函数或变量

A function or static data member declared with the constexpr specifier is implicitly an inline function or variable

所以我认为这可能与内联变量有关,但是在两个编译器下,对于c ++ 1z来说,以下操作均失败

So I thought it might have to do with inline variables, but the following fails for c++1z under both compilers

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


推荐答案

在C +之前+17,您需要以一个翻译单元(通常每个翻译单元为 .cpp)重新声明类之外的所有 static 变量。 code>文件,反之亦然,但这不是必需的)。正如您所指出的那样,C ++ 17引入了 inline 类成员变量,并且 static constexpr 变量自动合格。如您在第二个示例中所见,您不允许在类外重新声明内联变量,但对<$ c $进行了例外处理c> constexpr ,因为以前允许(实际上是必需的)这样做,但是不赞成使用该语法。

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). As you pointed out, C++17 introduces inline class member variables, and static constexpr variables automatically qualify. 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.

在[class。 static.data] p2,它允许非内联成员使用语法(类定义中的非内联静态数据成员的声明不是定义,并且可能是
,而不是cv void以外的不完整类型在类定义中未在内联
中定义的静态数据成员的定义应出现在包含该成员的类定义的名称空间范围中。)

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.")

在下一段中,该标准允许 constexpr 类外声明,并要求它们用于非 constexpr 数据(

In the next paragraph, the standard allows constexpr outside-of-class declarations and requires them for non-constexpr data (emphasis added):


如果是非易失性非内联 const 静态数据成员是整体的或枚举类型,其在类定义中的声明
可以在
中指定一个
brace-or-equal-initializer ,每个 initializer-clause assignment-expression
常量表达式(8.20)。如果该成员在程序中使用(6.2),则仍应在
命名空间范围内定义该成员,并且
命名空间范围定义不应包含 initializer 。内联
静态数据成员可以在类定义
中定义,并且可以指定括号或相等初始化器如果成员是使用 constexpr 声明符声明的
,则可以在
命名空间范围内重新声明它,而无需使用初始化程序
(此操作已弃用;请参见
D.1)。其他静态数据成员的声明中不得指定

brace-or-equal-initializer 。

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 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重新声明静态constexpr数据成员[depr.static_constexpr]:

And here’s the deprecation note, D.1 Redeclaration of static constexpr data members [depr.static_constexpr]:


用于与先前的C ++兼容在国际标准中,可以在没有初始化程序的
类外部冗余地声明constexpr静态数据成员。不建议使用此用法。 [示例:

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

-结束示例]

这篇关于现在可以重新定义constexpr静态数据成员了吗? (但不是内联const)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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