据我所知,一个很常见的情况是这样的
template<int i> class Class
{
public:
static constexpr int I = i;
static constexpr int J = constexprFunction(i);
// further Class implementation
};
几乎和我一样常见的错误是(事实上,我在这里的大部分问题都是因为我忘记了它并且不知道正确的问题是什么)如果成员被 odr-used 忘记了附加定义:
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 建议的文字。
最佳答案
此更改是由于内联变量提案 (P0386)。 static constexpr
将隐含 inline
,使定义变得多余。
In Annex D, add a new subclause, “Redeclaration of static constexpr data members”, D.X, with the following content: 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) }; const int A::n; // redundant declaration (definition in C++2014)
—end example]
关于您的问题:
Has this change other reasons than making the additional definitions useless?
本质上,没有。然而,除了您提到的用途之外,它还有其他用途(参见 question )。这个提议是有争议的,因为它可能会鼓励使用可变的全局状态。
Will it apply on
const static
member or not?
没有。 除非你把它注释为inline
。
does it all hold also for the situation at
Class:J
withconstexpr
functions?
是的。该提案处理链接,但不影响初始化规则。
关于c++ - C++17 之前/之后的 constexpr 静态成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39646958/