【问题标题】:G++ vs Clang : inconsistent behavior for constexpr and constG++ vs Clang:constexpr 和 const 的行为不一致
【发布时间】:2014-03-05 14:35:59
【问题描述】:

考虑以下代码:

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; }

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;
            ^

在我看来,GCC 是正确的(而我当然更喜欢 clang 行为)。尝试阅读标准时,我意识到我不足以作为语言律师做出决定。谁能确认一下?

【问题讨论】:

  • clang 3.5 在此代码上生成错误,live
  • clang项目发展很快,3.3已经过时了。
  • 你真的想在某处使用这样的代码吗?只是想知道。
  • 当然不是这样。如果您想了解一些背景信息,请参阅我在 stackoverflow.com/questions/22178366/… 上的回答
  • 仅供参考,这可能与 C++11 和 C++14 之间 constexpr 表达式的规则更改有关; C++14 为constexpr 表达式引入了宽松的规则,允许在constexpr 函数中改变 状态,因此C++14 中的constexpr 并不暗示const (尽管名字很尴尬)。

标签: c++ c++11 language-lawyer constexpr static-assert


【解决方案1】:

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

引用类型的变量或数据成员的 id 表达式,除非该引用具有前面的初始化,并使用常量表达式初始化;

但是B 确实有一个对引用常量表达式的先前初始化。

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

在这种情况下,B 的初始值设定项是 A,它是您可以得到的尽可能恒定的值。 AB 静态引用同一个对象。

所以,这是一个 GCC 错误。

【讨论】:

    【解决方案2】:

    如果不是语言律师,您一般不能将引用用作常量表达式,只能使用值(如果有例外,请纠正我)。从这个意义上说,最接近您的代码的有效值是:

    constexpr int A = 42;
    constexpr int B = A;
    
    static_assert(A == B, "Bug");
    

    但是,就我而言,Clang 3.3 和 GCC 4.8.1 都会按预期在您的代码中出现错误。

    编辑 显然我的知识还是有点狭隘,抱歉。根据链接可能存在例外情况,例如,如果语句是全局的,则在 main() 之外接受代码 (live)。

    【讨论】:

    • 我不认为你是对的。只需将constexpr 添加到const int &B = A; 行,我的代码似乎是正确的。
    • @hivert 见live - 我错过了什么吗?
    • 我不知道。这与我的计算机行为完全不同。
    • @hivert 查看我的编辑,当语句是全局的时代码编译,您没有在问题中指定。
    • @hivert 直观地说,因为两个不同对象的地址不能相等,我们在编译时就知道了。但是请参阅here 进行标准讨论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-03
    • 2016-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多