永远不会计算为常量表达式的 lambda() 可以是 C++ 中的“constexpr”函数吗?

Can lambda() that never evaluates to a constant expression be a `constexpr`-function in C++?

Lambda 的 operator() 根据 https://en.cppreference.com/w/cpp/language/lambda

隐式 constexpr

When this specifier (constexpr) is not present, the function call operator or any given operator template specialization will be constexpr anyway, if it happens to satisfy all constexpr function requirements

并且根据 https://en.cppreference.com/w/cpp/language/constexpr

constexpr 函数的要求

there exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression (for constructors, use in a constant initializer is sufficient) (since C++14). No diagnostic is required for a violation of this bullet.

在下一个例子中,函数 t() 总是通过调用 lambda l():

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

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

call to non-'constexpr' function '<lambda()>'

但是 Clang 接受了这个程序(直到函数 t() 被用在一个不断的求值中),这意味着它认为 l() 是一个 constexpr-函数,demo: https://gcc.godbolt.org/z/j1z7ee3Wv

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

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

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
}

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

[...] No diagnostic is required for a violation of this bullet.

编译器不一定需要证明没有一组参数值允许函数 return 常量表达式。另一方面,编译器可以很容易地验证给定的参数值,结果不是常量表达式。