为什么这些片段由GCC处理不同?

时间:2015-12-21 13:55:28

标签: c++ gcc g++ language-lawyer c++14

第一个代码段编译时没有任何警告(live example):

#include <iostream>

struct A {
  constexpr A(): i(5){}
  constexpr operator int() { return 5; }
  int i;
};

int main() {
    A a;
    int b[a]{ 0, 1, 2, 3, 4 };
    std::cout << b[4] << '\n';
}

现在通过在转换运算符live example中返回i来更改上述代码段:

constexpr operator int() { return i; }

GCC警告b是VLA。

对我来说,这两个变体似乎都符合C ++ 14中的段落§5.19[expr.const] / 3。

2 个答案:

答案 0 :(得分:17)

您正在i上执行l-t-r转换,但是对于[expr.const] /(2.7)这里不违反,(2.7.3)必须适用:

enter image description here

(2.7.1)涉及完整的对象,(2.7.2)谈论字符串文字,(2.7.4)是关于生命周期在表达式的评估中开始的对象 - 不适用于a的声明在b之前。

a定义为constexpr且代码符合要求。

澄清标准内容的一个小附录:括号内的表达式必须是std::size_t[dcl.array]/1)类型的转换常量表达式,在[expr.const]/4中定义为< / p>

  

转换常量表达式 T是一个表达式,隐式转换为类型T,其中转换为   表达式是一个常量表达式和[......满足要求...]

因此,实际上,标准是否对

感兴趣
constexpr std::size_t s = a; 

是有效的。由于上述原因,它不是 - 试图使用先前定义的非constexpr对象的子对象。

答案 1 :(得分:4)

数组大小必须是编译时常量,但在第二个示例中,A::i的初始化在运行时之前不会发生。