在C++11标准中,它在什么地方指定在翻译期间何时可以计算conexpr函数?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (39)

仅仅因为一个函数(或构造函数)......

  • 被宣布为constexpr和
  • 函数定义符合constexpr的要求

...并不意味着编译器会在翻译过程中评估constexpr函数。我一直在浏览C ++ 11 FDIS(N3242,可从http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/获取)来尝试确定两件事:

  • 编译器何时有义务在翻译过程中评估constexpr函数?
  • 编译器何时允许在翻译期间评估constexpr函数?

第5.19节第1段说可以在翻译期间评估常量表达式。就我所能理解的而言,第5.19节的其余部分阐述了在constexpr函数的定义中什么是有效的规则。

我知道我可以通过将constexpr函数的结果声明为constexpr来强制在翻译过程中进行constexpr评估。喜欢这个:

// Declaration
constexpr double eulers_num() { return 2.718281828459045235360287471; }

// Forced evaluation during translation
constexpr double twoEulers = eulers_num() * 2.0;
static_assert(twoEulers > 5.0, "Yipes!");

到目前为止,我一直无法找到FDIS中的段落:

  • 力量twoEulers在翻译或评估过程中进行评估
  • 指定编译器在翻译期间可能或必须评估constexpr函数的其他情况。

我特别感兴趣的是,翻译过程中的constexpr评估是由以下因素触发的:

  1. 当传递给constexpr函数的所有参数都是文字或
  2. 重载解析期间的隐含对象参数(第13.3.1节第3段)可以是constexpr或需要一个文字(如数组尺寸),或
  3. 完全是其他的东西。
提问于
用户回答回答于

​​表达是否在翻译时进行评估以及是否在运行时进行评估是完全独立的问题。由于常量表达式不会产生副作用,因此可以对其进行任意次数的评估,并且无论是在翻译时还是运行时都不会对其进行评估。

假设常量表达式是一个大数组(不是一个std::array数组),这是完全合法的,程序并不表示它具有静态存储。假设只有数组的元素7用于需要编译时计算的上下文中。编译器计算整个数组,使用元素7,丢弃它,并插入代码以在运行时计算它,而不是使用整个计算数组膨胀二进制文件是非常合理的。我相信这不是一个理论问题; 我已经在各种情况下用各种编译器观察过它。constexpr没有暗示static

当然,如果编译器可以确定该数组在运行时没有被使用,它甚至可能不会插入代码来计算它,但这是另一个问题。

如果你在运行时使用这样的对象,并且想要向编译器指出在程序期间值得保留它,那么你应该将其声明为static

用户回答回答于

只有constexpr在实际可能的情况下,才允许在编译时评估调用。请记住,该规范在“asf”规则下运行。所以如果你不能区分这个区别,编译器可以做任何想做的事情。

在编译时,编译器需要constexpr调用时评估调用,而实际上它需要编译时的答案。例如:

constexpr int foo() {return 5;}

std::array<float, foo()> arr;

编译器需要在编译时知道数组的大小。因此,它必须在编译时评估常量表达式。如果constexpr函数不能在编译时执行,则会出现编译时错误。

扫码关注云+社区