在C++ 17之前/之后的constexpr静态成员

mar*_*lam 15 c++ static constexpr c++17

据我所知,一个非常常见的情况是这样的

template<int i> class Class
{
public:
    static constexpr int I = i;
    static constexpr int J = constexprFunction(i);
    // further Class implementation
};
Run Code Online (Sandbox Code Playgroud)

几乎同样普遍的我看到错误(事实上我的大部分问题是因为我忘记了,并且不知道,正确的问题是什么)如果成员使用的话会忘记附加的定义:

template<int i> constexpr int Class<i>::I;
template<int i> constexpr int Class<i>::J;
Run Code Online (Sandbox Code Playgroud)

现在我读了cppreference:Definitions和ODR以及cppreference:静态成员,声明这是C++ 17不推荐使用的.这对我来说似乎很棒,因为它避免了很多错误.但是还有其他问题出现了:

1)这改变了其他原因,而不是使附加定义无用吗?(另见本问题的最后一段)

2)在cppreference的最后一个例子中:静态成员似乎也适用于const static成员 - 但规则只声明了constexpr成员.是否适用于const static会员?

3)所有的例子,我发现用一个简单的定义一样Class::I-做这一切还保持了形势Class:Jconstexpr功能?

简要说明在C++ 17和C++ 17之前最佳实践是什么.总而言之,这对我来说似乎是一个非常棘手的变化,因为它会产生很多代码,这些代码之前需要"格式化不需要诊断"才能获得良好的代码(据我所知......).因此,会产生代码,对于较早的(前17版)编译器仍然是"不需要的非诊断" - 但只要不需要使用odr,这些就不会抱怨.

编辑:更正了Aaron McDaid建议的文字.

met*_*fox 12

此更改是由内联变量提议(P0386)引起的.static constexpr意味着inline,使定义多余.

在附录D中,添加一个新的子条款"静态constexpr数据成员的重新声明",DX,具有以下内容:为了与先前的C++国际标准兼容,constexpr静态数据成员可以在没有初始化器的情况下在类外冗余重新声明.不推荐使用此用法.

[例:

struct A {
static constexpr int n = 5; // definition (declaration in C++2014)
};
const int A::n; // redundant declaration (definition in C++2014)
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

关于你的问题:

除了使其他定义无用之外,这是否会改变其他原因?

实质上,没有.然而,除了你提到的那个之外,它还有其他用途(见这个问题).该提案存在争议,因为它可能会鼓励使用可变的全球状态.

是否适用于const static会员?

不,除非你注释为inline.

它是否也适用于Class:J具有constexpr功能的情况?

是.该提案涉及链接但不影响初始化规则.