我对constexpr功能感到困惑?

Ocx*_*cxs 4 c++ constexpr c++11

在C++ Primer,第五版,§6.5.2中:

constexpr函数被定义像任何其他的功能,但必须满足某些限制:返回类型和每一个参数的类型必须是文字型,和函数体必须只包含一个返回语句(第2.4.4节,第66页.)

但本章的另一句话(第239页):

允许constexpr函数返回不是常量的值

// scale(arg) is a constant expression if arg is a constant expression
constexpr size_t scale(size_t cnt) { return new_sz() * cnt; }
Run Code Online (Sandbox Code Playgroud)

这是一个矛盾的总结吗?我很困惑.
返回类型scale是文字类型?
更新:文字类型和常量之间有什么区别?

Sha*_*our 8

首先,我认为作者的意思是constexpr函数不必导致常量表达式,这是一个可以在编译时进行求值的表达式.

constexpr函数只会产生一个常量表达式,如果函数的参数也是常量表达式,并且后面的注释恰好说明:

// scale(arg) is a constant expression if arg is a constant expression
Run Code Online (Sandbox Code Playgroud)

以及之后的示例也演示了此行为:

int arr[scale(2)]; // ok: scale(2) is a constant expression
int i = 2; // i is not a constant expression
int a2[scale(i)]; // error: scale(i) is not a constant expression
Run Code Online (Sandbox Code Playgroud)

在C++中(与C99相反),因为数组大小必须是常量表达式,因此最后一种情况是错误,因为参数to scale不是常量表达式.

这是与函数的返回类型不同的概念,它必须是文字类型,它是以下任何一种:

  • void(因为c ++ 14)(因此constexpr函数可以返回void)
  • 标量类型,包括算术类型,枚举类型,指针类型,指向成员类型的指针,std :: nullptr_- t和这些类型的cv限定版本)
  • 参考类型
  • 一个文字类型的数组
  • 具有以下所有属性的类类型:
    • 有一个简单的析构函数,
    • 或者是
      • 聚合类型
      • 具有至少一个constexpr(可能是模板)构造函数的类型,该构造函数不是复制或移动构造函数
    • 所有非静态数据成员和基类都是非易失性文字类型.


小智 6

这并不矛盾.除了强制返回类型必须是"文字类型"之外,草案标准还规定对constexpr函数的调用不必出现在常量表达式中.从C++ 11草案标准:

§7.1.5/ 7对constexpr函数的调用产生与constexpr 在所有方面调用等效非函数相同的结果,除了对constexpr函数的调用可以出现在常量表达式中.