考虑以下代码(gcc.godbolt.org提供):
template <typename TF>
constexpr auto fn_x(TF f)
{
return f();
}
constexpr auto get_x()
{
return fn_x([]{ return 0; });
}
int main()
{
auto res = get_x();
}
它在g 5.3. x和更新版本(包括g 6. x. x)下编译。
它不在Clang3.7下编译。x及更高版本,出现以下错误:
error: constexpr function never produces a constant expression [-Winvalid-constexpr]
constexpr auto get_x()
^
note: subexpression not valid in a constant expression
return fn_x([]{ return 0; });
使用gcc和clang编译代码的一个可能的解决方案是使用带有decltype
的“间接层”,同时在定义lambda的函数中去掉constepr
。锁销。组织链接。
根据标准,这里哪个编译器是正确的?
两个编译器一致认为,get_x()
不能在常量表达式中使用。您可以通过更改auto res=get_x()来判断
toconstexpr auto res=get_x()代码>,其中GCC将同样拒绝该代码。
至于像clang那样在函数定义时检测它,而不是像gcc那样在函数使用时检测它,两者都是允许的:(强调我的)
7.1.5 Constexpr说明符[dcl.constexpr]
5对于非模板、非默认的constepr
函数或非模板、非默认、非继承的constepr
构造函数,如果不存在参数值,使得函数或构造函数的调用可能是核心常量表达式(5.19)的求值子表达式,则程序格式错误;无需诊断。[...]
在一般情况下,不可能可靠地检测是否存在允许在常量表达式中使用结果的函数调用,这就是为什么诊断是可选的。