仅在 constexpr 函数主体中的未计算上下文中使用的参数

Argument only used in unevaluated context within the body of a constexpr function

本文关键字:上下文 参数 计算 主体 constexpr 仅在 函数      更新时间:2023-10-16

以下一段代码已成功使用 gcc 5.3.0 编译,但未能使用 clang 3.7.0 编译。在这两种情况下,我都使用了具有相同命令行选项的在线 coliru 编译器:-std=c++14 -O2 -Wall -pedantic -pthread。

#include <cstdio>
// Definition of constexpr function 'foo'.
constexpr std::size_t foo(const int& arg_foo) { return sizeof(arg_foo); }
// Definition of function 'test'.
void test(const int& arg)
{ 
  // The following line produces an error with clang.
  constexpr std::size_t res_foo = foo(arg);
  // Print the result returned by the 'foo' function.
  std::printf("res_foo = %lun", res_foo);
}
// Definition of function 'main'.
int main(int argc, const char* argv[])
{
  // Test function call.
  test(argc);
  // Return statement.
  return 0;
}

Clang 拒绝它,并显示以下错误:

error: constexpr variable 'res_foo' must be initialized by a constant expression
constexpr size_t res_foo = foo(arg);
                           ~~~~^~~~

由于两个编译器之间的这种差异,我想知道这是否是一段有效的代码。如果没有,我想更好地了解为什么会这样。

您正在将const值和constexpr值混合在一起。constexpr 的定义是在编译时已知的值。但是 argc 变量仅在运行时已知(它是传递给可执行文件的许多参数)。因此,您不能将其分配给另一个constexpr变量 - res_foo .从res_foo定义中删除constexpr将使代码可编译。

constconstexpr 之间的区别可以简化为如下所示:
const - 我不会更改此值
constexpr - 这个值在编译时是已知的我不会改变它

我的猜测是GCC能够使用O2编译此代码,因为您没有使用arg_foo参数,并且在编译时已知它的大小。但它在语法上仍然是不正确的 - 编译器应该发出一个错误,因为非 constexpr 值被分配给 constexpr 变量。

该程序的格式良好,因为foo(arg)是 C++14 5.20/2 中定义的 prvalue 核心常量表达式。 特别是,在评估期间没有左值到右值的转换,这将使它不是一个常量表达式。