According to cppreference, both gcc and clang have completed the implementation of P1102R2 ("Down with ()!") recently, which means we can define lambda expressions more concisely in C++23.
But I found that they are inconsistent with a certain form:
auto l = []<auto> noexcept requires true {};
clang accepts this form, and gcc rejects its grammar.
Which compiler should I trust? Is this lambda well-formed or ill-formed in C++23?
Perhaps because of the pressure of public opinion, clang quickly fixed the 49736 within five days after I reported it.
As I tried further, I accidentally found out that gcc also rejected the following valid form, which made me report the 99850 and it was fixed after 2 weeks.
auto l = []<auto> requires true -> void {};
Thanks for reminding me of how pointless this feature is.
The correct answer is: no, that's not a well-formed lambda. The grammar is defined in [expr.prim.lambda.general]:
In our case, to start with we have:
[]<auto> noexcept requires true {};
[]
is the lambda-introducer<auto>
matches <template-parameter-list>
and now we know we're the 2nd kind lambda-expression. So grammatically, we're need to follow with a requires-clause (optionally) then a lambda-declarator then a compound-statement.noexcept
does not match requires-clause, so now we're parsing a lambda-declarator. A lambda-declarator could start with (parameter-declaration-clause)
but we don't have that, so we're just looking for lambda-specifiers. We consume the noexcept
as part of noexcept-specifier.requires true
does not fit either attribute-specifier-seq or trailing-return-type so we have neither of those, and now we're done with lambda-specifiers so we're done with lambda-declarator. At this point, we're looking for a compound-statement. But we don't have that, so this is an error.Basically, there are two spots you can put a requires-clause: either directly after the template parameters or, if we have function parameters, after the lambda-specifiers after the function parameters. So this works:
[]<auto> requires true noexcept {};
as does this:
[]<auto>() noexcept requires true {};
as does this:
[]<auto> requires true () noexcept requires true { };
But not the one in OP.
Also, don't write this.