静态成员声明为 const 但初始化为 constexpr

Sta*_*nny 5 c++ initialization constexpr c++17

考虑一个具有常量成员的类:

class foo {
public:
    const static int N;
};
Run Code Online (Sandbox Code Playgroud)

foo::N 需要初始化:

constexpr int foo::N = 5;
Run Code Online (Sandbox Code Playgroud)

并注意使用constexpr限定符而不是const这里似乎是一个错误。

但是 GCC、Clang 和 MSVC 都编译得很好!

  • 语言中是否有允许在此处更改限定符的内容?
  • 这是所有三个编译器都忽略的错误吗?

Clang 甚至允许同时使用两个限定符版本:

constexpr int foo::N = 3;
const int foo::N = 5;

int main(){
    return foo::N; //returns 3
}
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?

Dav*_*ing 2

由于显然已声明但未定义的变量的值不能在常量表达式中使用,因此constexpr仅适用于变量的定义。(当然,如果变量是内联的,也许因为是声明的静态成员constexpr,所以每个定义都必须有constexpr。)这意味着const(在变量本身上:constexpr char*char *const,不是const char*),所以你没有\xe2\x80\x99t更改了变量\xe2\x80\x99s类型。这与

\n\n
// foo.hpp\nextern const int x;\n\n// foo.cpp\nconstexpr int x=2;\n
Run Code Online (Sandbox Code Playgroud)\n\n

这也许并不令人惊讶。

\n\n

所以一切都很好!变量\xe2\x80\x99s值只能在包含定义的翻译单元中用于常量表达式,但这\xe2\x80\x99s并不奇怪,并且可以很容易地被解释为模块化功能。Clang 允许两个定义是有问题的:可能它\xe2\x80\x99 试图忽略类中定义的 constexpr 静态数据成员的(从 C++17 开始已弃用)类外定义。

\n