在非“constexpr”上下文中的“constexpr”函数中使用lambda:clang vs gcc
Using a lambda in a `constexpr` function in a non-`constexpr` context: clang vs gcc
请考虑以下代码(在 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 编译的一个可能的解决方案是使用带有 decltype
的"间接层",也摆脱了定义 lambda 的函数中的constexpr
:gcc.godbolt.org 链接。
根据标准,哪个编译器是正确的?
两个编译器都同意get_x()
不能在常量表达式中使用。您可以通过将auto res = get_x();
更改为constexpr auto res = get_x();
来判断,GCC 将同样拒绝它。
而不是像 gcc 那样在函数使用时检测它,两者都是允许的:(强调我的)
在7.1.5 constexpr 说明符 [dcl.constexpr]
5 对于非模板、非默认
constexpr
函数或非模板、非默认、非继承constexpr
构造函数,如果不存在参数值,使得函数或构造函数的调用可以是核心常量表达式的计算子表达式 (5.19),则程序格式不正确;无需诊断。[...]
一般情况下,不可能可靠地检测是否存在允许在常量表达式中使用结果的函数调用,这就是诊断是可选的原因。
相关文章:
- Clang 8 带有静态 constexpr 和数组的链接器错误 - 错误是什么以及如何解决它?
- 类无法访问自己的私有静态 constexpr 方法 - Clang bug?
- ConstexPR :GCC比Clang更努力地评估ConstexPR
- constexpr 使用 clang 编译 TensorFlow 时出错
- constexpr 函数的常量引用参数:gcc/msvc vs clang/icc
- 为什么 clang 并不总是为相同的静态 constexpr 产生常量值
- l值引用对象上的Constexpr成员函数:Clang和gcc不同意
- ADL 在 constexpr 函数中不起作用(仅限 clang)
- Clang, std::next, libstdc++ and constexpr-ness
- Clang声称通用lambda参数的constexpr成员不是constexpr
- enable_if is_same constexpr函数使MSVC失败(但在Clang,GCC中效果很好)
- Clang说is_same_v<int,double>的用法不是constexpr,不知道它怎么不是
- 海湾合作委员会和Clang在lambda的constexpr-ness上存在分歧?
- constexpr 唯一 ID,使用 clang 编译,但不使用 GCC 编译
- MSVC 和 clang for if constexpr 分支的不同行为
- constexpr(但不是真正的)构造函数在GCC中编译,而不是在Clang中编译
- 如果Constexpr - clang vs.GCC,则非constexpr变量
- Clang 在编译时不会计算非 constexpr 变量的 constexpr 函数的值
- gcc 和 clang 中 constexpr 静态成员变量的链接器错误
- 使用 constexpr 函数的结果作为模板参数(clang vs gcc)