constexpr未定义的行为

Fle*_*exo 18 c++ undefined-behavior language-lawyer c++11

我一直在试验constexpr.在我的测试编译器(g ++ 4.6)上,无法编译带有关于越界访问的错误.是一个编译器需要在编译时被发现呢?

#include <iostream>

constexpr const char *str = "hi";

constexpr int fail() {
  return str[1000]; // Way past the end!
}

template <int N>
struct foo {
  static void print() { std::cout << N << std::endl; }
};

int main() {  
  foo<fail()>::print();
}
Run Code Online (Sandbox Code Playgroud)

Pot*_*ter 11

§5.19/ 2(在第二页;它确实应该分成许多段落)禁止包含的常量表达式

- 除非适用,否则为左值 - 右值转换(4.1)

- 一个整数或枚举类型的glvalue,它引用具有前面初始化的非易失性const对象,用常量表达式初始化,或者

- 文字类型的glvalue,引用用constexpr定义的非易失性对象,或引用此类对象的子对象

str[1000]转换为* ( str + 1000 ),str与入站数组访问不同,不引用子对象.所以这是一个可诊断的规则,编译器需要抱怨.

编辑:似乎对这种诊断是如何产生了一些混淆.当需要保持不变时,编译器会根据§5.19检查表达式.如果表达式不满足要求,则编译器需要进行投诉.实际上,需要针对可能导致未定义行为的任​​何事物验证常量表达式.*这可能涉及也可能不涉及尝试评估表达式.

 *在C++ 11中,"一个没有数学定义的结果." 在C++ 14中,"一个具有未定义行为的操作",根据定义(§1.3.24),它忽略了实现可能定义为回退的行为.

  • @Tomalak:没有解除引用,因为首先不能形成表达式.§5.19描述了可以包含在常量表达式中的内容.这不可能.故事结局. (2认同)
  • @Omni:`str [1]`是一个文字类型的glvalue的子对象,它指的是用constexpr定义的非易失性对象.`str [1000]`不是.一个是定义明确的,另一个是不允许的. (2认同)

Sha*_*our 5

是的,编译器应该在编译的时候赶上这一点,如果我们看一下部分5.19 常量表达式2的的草案C++标准它列出了作为常量表达式排除:

- 具有未定义行为的操作 [注意:包括,例如,有符号整数溢出(第5条),某些指针算术(5.7),除零(5.6)或某些移位操作(5.8) - 结束注释];

据我所知,问题695是未定义的行为是非const的,应该发出诊断:

CWG的共识是,像1/0这样的表达式应该被简单地视为非常数; 在需要常量表达的上下文中使用表达式会导致任何诊断.

您可以在我自己回答的问题中找到更多详细信息,这些问题也可用于此功能.