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

时间:2016-09-22 19:01:08

标签: 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
};

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

template<int i> constexpr int Class<i>::I;
template<int i> constexpr int Class<i>::J;

现在我读了cppreference: Definitions and ODRcppreference: static members,其中说明了C ++ 17已弃用。这对我来说似乎很棒,因为它避免了很多错误。但还有其他问题出现了:

1)这是否会改变其他原因而不是使其他定义变得无用? (另见本问题的最后一段)

2)在cppreference: static members的最后一个示例中,它似乎也适用于const static成员 - 但该规则仅指明constexpr成员。它是否适用于const static成员?

3)我发现的所有示例都使用了一个简单的定义,例如Class::I - 它是否也适用于Class:J具有constexpr函数的情况?

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

修改:更正了Aaron McDaid建议的文字。

1 个答案:

答案 0 :(得分:11)

此更改是由内联变量提案(P0386)引起的。 static constexpr将暗示inline,使定义变得多余。

  

在附件D中,添加一个新的子条款“静态constexpr数据成员的重新声明”,D.X,其中包含以下内容:   为了与先前的C ++国际标准兼容,可以在类外部冗余地重新声明constexpr静态数据成员而不使用初始化程序。不推荐使用此用法。

     

[实施例:

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

-end example]

关于你的问题:

  

这是否会改变其他原因而不是使其他定义变得无用?

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

  

是否适用于const static会员?

没有。 除非您将其注释为inline

  

这一切是否也适用于Class:J constexpr函数的情况?

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