在非`constexpr`上下文中的`constexpr`函数中使用lambda:clang vs gcc

时间:2016-02-26 18:31:39

标签: c++ lambda language-lawyer c++14 constexpr

请考虑以下代码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的函数中的constexprgcc.godbolt.org link

根据标准,这里的编译器是否正确?

1 个答案:

答案 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),程序 格式错误;无需诊断 。 [...]

在一般情况下,不可能可靠地检测是否存在允许将结果用于常量表达式的函数调用,这就是诊断是可选的原因。