请考虑以下代码(available on 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 )下编译。
它不能在 clang ++ 3.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编译代码的可能解决方案是使用&#34;间接层&#34;使用decltype
,还可以删除定义lambda的函数中的constexpr
:gcc.godbolt.org link。
根据标准,这里的编译器是否正确?
答案 0 :(得分:6)
两个编制者都同意get_x()
不能用于常量表达式。您可以将auto res = get_x();
更改为constexpr auto res = get_x();
,GCC将同等地拒绝它。
至于在功能定义时检测它像clang一样,而不是像gcc那样在功能上使用,两者都是允许的:(强调我的)
7.1.5 constexpr说明符[dcl.constexpr]
5对于非模板,非默认的
constexpr
函数或非模板,非默认的,非继承的constexpr
构造函数,如果不存在参数值,则调用函数或构造函数可以是核心常量表达式的评估子表达式(5.19),程序 格式错误;无需诊断 。 [...]
在一般情况下,不可能可靠地检测是否存在允许将结果用于常量表达式的函数调用,这就是诊断是可选的原因。