参数仅用于constexpr函数体内未评估的上下文中

时间:2016-01-21 13:47:09

标签: c++ c++14 constexpr

以下代码已成功使用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 = %lu\n", 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);
                           ~~~~^~~~

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

2 个答案:

答案 0 :(得分:1)

您将$validatorconst值混合在一起。 constexpr的定义是编译时已知的值。但constexpr变量仅在运行时已知(它是传递给您的可执行文件的一些参数)。因此,您无法将其分配给另一个argc变量 - constexpr。从res_foo定义中移除constexpr将使您的代码可编辑。

res_fooconst之间的区别可以简化为以下内容:
constexpr - 我不打算更改此值
const - 这个值在编译时已知我不会改变它

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

答案 1 :(得分:0)

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