C++ 获取constexpr全局变量(非静态成员)的链接器符号

C++ 获取constexpr全局变量(非静态成员)的链接器符号,c++,c++11,C++,C++11,我可以为静态成员编写以下内容: // foo.h struct A { static constexpr int x = 2; }; // foo.cpp constexpr int A::x; 对顶级变量也可以这样做吗?这在C++11中不起作用: // foo.h constexpr int x = 2; // foo.cpp constexpr int x; 它失败于: <source>:3:15: error: redefinition of 'constexpr

我可以为静态成员编写以下内容:

// foo.h
struct A {
    static constexpr int x = 2;
};
// foo.cpp
constexpr int A::x;
对顶级变量也可以这样做吗?这在C++11中不起作用:

// foo.h
constexpr int x = 2;
// foo.cpp
constexpr int x;
它失败于:

<source>:3:15: error: redefinition of 'constexpr const int x'

向表达式中添加static也没有帮助。我知道一个解决方法是将其设置为静态成员,但我想了解非成员版本不起作用的原因。

这是一个PEBKAC。您可以获取constexpr变量的地址:

constexpr int x = 2;
const int* const f() {
    return &x;
}

这是正确的:将生成x的链接器部分,而不管该声明重复多少次。因此,没有什么好的理由想要使用静态constexpr成员所需的相同习惯用法。

第一个示例有效,因为在结构中只声明变量x,然后在源文件中定义它。在第二个示例中,在包含头文件的每个源文件中都有一个定义,再加上foo.cpp源文件中的一个定义。不允许有两个或多个定义。静态constexpr成员也不再需要此习惯用法,事实上,从C++17开始,此习惯用法已被删除。请注意,此示例的行为在C++14和C++17之间有所不同!在C++14中,命名空间范围constepr变量具有内部链接,因此x的地址将因不同的转换单元而不同。在C++17中,变量上的constexpr意味着内联,而内联变量在C++17中是一个新事物,变量具有外部链接,并且始终具有相同的地址。