Reputation: 21099
Lambda's operator()
is implicitly constexpr
according to https://en.cppreference.com/w/cpp/language/lambda
When this specifier (
constexpr
) is not present, the function call operator or any given operator template specialization will beconstexpr
anyway, if it happens to satisfy allconstexpr
function requirements
And a requirement of a constexpr
-function according to https://en.cppreference.com/w/cpp/language/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.
In the next example, the function t()
always throws an exception by calling lambda l()
:
auto l = []()->bool { throw 42; };
constexpr bool t() { return l(); }
GCC rejects this function with the error:
call to non-'constexpr' function '<lambda()>'
but Clang accepts the program (until the function t()
is used in a constant evaluation), meaning that it considers l()
a constexpr
-function, demo: https://gcc.godbolt.org/z/j1z7ee3Wv
Is it a bug in Clang, or such compiler behavior is also acceptable?
Upvotes: 3
Views: 191
Reputation: 122228
All three compilers do issue an error when you actually try to use the result of t()
in a context that requires a constant expression. 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
}
As mentioned in a comment by NathanOliver, your quote already states:
[...] No diagnostic is required for a violation of this bullet.
Compilers need not necessarily proove that there is no set of argument values that allow the function to return a constant expression. On the other hand, a compiler can easily verify for a given argument value, that the result is not a constant expression.
Upvotes: 6