G ++ vs Clang:constexpr和const的行为不一致

hiv*_*ert 5 c++ static-assert language-lawyer constexpr c++11

请考虑以下代码:

constexpr const int A = 42;

const int &B = A;
static_assert(&A == &B, "Bug");

constexpr const int &C = B;
static_assert(&A == &C, "Bug");

int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)

它完全被clang 3.3版所接受,而g ++(SUSE Linux)4.8.1 20130909 [gcc-4_8-branch revision 202388拒绝它:

bug2.cpp:5:1: error: non-constant condition for static assertion
 static_assert(&A == &B, "Bug");
 ^
bug2.cpp:5:1: error: the value of ‘B’ is not usable in a constant expression
bug2.cpp:2:12: note: ‘B’ was not declared ‘constexpr’
 const int &B = A;
            ^
Run Code Online (Sandbox Code Playgroud)

在我看来,海湾合作委员会是正确的(而我当然更喜欢铿锵行为).试图阅读标准我意识到我不够语言律师来决定.任何人都可以证实吗?

Pot*_*ter 3

the value of \xe2\x80\x98B\xe2\x80\x99 is not usable in a constant expression是不正确的。您没有对 B 执行左值到右值的转换,这是“值”的通常含义;你只是获取它的地址。唯一相关的常量表达式规则禁止:

\n\n
\n

引用引用类型的变量或数据成员的 id 表达式,除非引用具有预先初始化(使用常量表达式初始化);

\n
\n\n

然而B,确实有一个对引用常量表达式的预先初始化。

\n\n
\n

引用常量表达式是左值核心常量表达式,它指定具有静态存储持续时间的对象或函数。

\n
\n\n

在本例中,B\ 的初始值设定项是A,它是您可以获得的尽可能恒定的值。AB静态引用同一个对象。

\n\n

所以,这是一个 GCC 错误。

\n