I know it's like opening the Pandora box but it doesn't stop bothering me. Consider a simple example:
#include <type_traits>
template <auto>
struct Foo: std::false_type { };
template <>
struct Foo<[](){return 1;}()>:std::true_type { };
int main() {
static_assert(Foo<1>::value);
}
I know lambdas cannot be declared inside unevaluated context, but obviously this is not the case here. What is even more weird clang 5.0.0 (which, I guess, first partially supports constexpr lambda) does compile it.
Is it a compiler bug or will C++17 allow this?
No, that is a compiler bug. gcc 7.1 correctly rejects the code.
[expr.prim.lambda]/2:
A lambda-expression is a prvalue whose result object is called the closure object. A lambda-expression shall not appear in an unevaluated operand, in a template-argument, in an alias-declaration, in a typedef declaration, or in the declaration of a function or function template outside its function body and default arguments.
As you can see from the part that I marked as bold, a lambda expression cannot appear in a template argument list.
This is also made clear in a subsequent note:
[ Note: The intention is to prevent lambdas from appearing in a signature. — end note ]
If I were to guess, I would say that the bug comes about because starting with C++17, lambdas are implicitly constexpr
, which makes them valid to be called in compile time expressions, like template arguments. But actually defining a lambda in a template argument is still illegal.
Note that this restriction has been lifted in C++20. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With