从不求值为常量表达式的 lambda() 可以是 C++ 中的“constexpr”函数吗?

Fed*_*dor 3 c++ lambda language-lawyer constexpr

Lambdaoperator()隐式地constexpr根据https://en.cppreference.com/w/cpp/language/lambda

当此说明符 ( constexpr) 不存在时,函数调用运算符或任何给定的运算符模板特化将constexpr无论如何,如果它碰巧满足所有constexpr函数要求

constexpr以及根据https://en.cppreference.com/w/cpp/language/constexpr的 -function的要求

至少存在一组参数值,使得函数的调用可以是核心常量表达式的计算子表达式(对于构造函数,在常量初始值设定项中使用就足够了)(C++14 起)。违反此项目符号无需进行诊断。

在下一个示例中,该函数t()始终通过调用 lambda 引发异常l()

auto l = []()->bool { throw 42; };
constexpr bool t() { return l(); }
Run Code Online (Sandbox Code Playgroud)

GCC 拒绝此函数并出现错误:

call to non-'constexpr' function '<lambda()>'
Run Code Online (Sandbox Code Playgroud)

但 Clang 接受该程序(直到t()在不断的评估中使用该函数),这意味着它认为是l()一个constexpr函数,演示:https: //gcc.godbolt.org/z/j1z7ee3Wv

这是 Clang 中的错误,还是这样的编译器行为也是可以接受的?

for*_*818 6

t()当您实际尝试在需要常量表达式的上下文中使用 的结果时,所有三个编译器都会发出错误。例如

auto l = []()->bool { throw 42; };
constexpr bool t() { return l(); }

template <bool x>
struct dummy {};

int main() {
   dummy< t() > d;   // error: t() is not a constant expression
}
Run Code Online (Sandbox Code Playgroud)

正如 NathanOliver 在评论中提到的,您的引述已经指出:

[...] 违反此项目符号无需进行诊断。

编译器不一定需要证明不存在允许函数返回常量表达式的参数值集。另一方面,编译器可以轻松验证给定参数值的结果不是常量表达式。