据我所知,一个非常常见的情况就像是
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 ODR和cppreference: 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建议的文字。
答案 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
函数的情况?
是。该提案涉及链接但不影响初始化规则。