仅在 constexpr 函数主体中的未计算上下文中使用的参数
Argument only used in unevaluated context within the body of a constexpr function
以下一段代码已成功使用 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
将使代码可编译。
const
和 constexpr
之间的区别可以简化为如下所示:
const
- 我不会更改此值
constexpr
- 这个值在编译时是已知的,我不会改变它
我的猜测是GCC能够使用O2编译此代码,因为您没有使用arg_foo
参数,并且在编译时已知它的大小。但它在语法上仍然是不正确的 - 编译器应该发出一个错误,因为非 constexpr 值被分配给 constexpr 变量。
该程序的格式良好,因为foo(arg)
是 C++14 5.20/2 中定义的 prvalue 核心常量表达式。 特别是,在评估期间没有左值到右值的转换,这将使它不是一个常量表达式。
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 将有状态的 lambda 传递到 C 样式函数中,而无需上下文参数
- 具有std::initializer_list参数的非成员函数(/non构造函数上下文)的重载解析
- 如何创建一个版本的 boost::range::transform,该版本具有用于捕获上下文的额外参数
- 为什么在此上下文中非类型模板参数不能是自动的
- SetPixelFormat() 中的第三个参数对于 OpenGL 上下文创建有什么意义?
- 有没有办法将别名模板推导到模板模板参数,同时仍保留其被推导上下文的属性
- 是默认模板模板参数值推导的上下文
- 在spirit parser Action中,在上下文参数上编译boost :: bind(成员函数)上的错误
- c++:当回调不提供用户参数时如何获取上下文?
- Qt:上下文菜单/与参数连接