The question Lambda expressions as class template parameters asks about the possibility of using lambda expressions as class template parameters.
The answer to the question was no. However, it was about C++11.
Has the situation changed in the new standard, C++14?
No the situation in C++14 has not changed at all and in fact the language in section 5.1.2
Lambda expressions paragraph 2 has been tightened from:
A lambda-expression shall not appear in an unevaluated operand (Clause 5).
to:
[...]A lambda-expression shall not appear in an unevaluated operand (Clause 5), in a templateargument, 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. [ Note: The intention is to prevent lambdas from appearing in a signature. —end note ][...]
Defect report 1607. Lambdas in template parameters lead to this change.
The defect report only obliquely deals with the rationale for disallowing this but we can find a very detailed explanation for why this is disallowed in Rationale for lambda-expressions not being allowed in unevaluated contexts. The reasons boil down to:
SFINAE
Given the rationale for this restriction it seems unlikely to change.
Has the situation changed in the new standard, C++14?
A Lambda expression shall still not appear in an unevaluated operand - the same quote as the one in Xeo's Post also exists in the latest publicly available draft N3797, in the exact same place.
However, every closure type has a deleted default constructor (N3797, §5.1.2/20):
The closure type associated with a lambda-expression has a deleted (8.4.3) default constructor and a deleted copy assignment operator.
So, for portabiliby and standard conformance (and probably for the code to work on reasonable compilers), you would need to pass a closure object to the constructor of the instantiated class to copy from. But to pass a closure object of the same type as the template argument of that specialization you have to define it first anyway:
using my_map_type = map<int, int, decltype([] (auto&& lhs, auto&& rhs) {return lhs < rhs*4;})>;
// Assuming the above compiles
my_map_type m( [] (auto&& lhs, auto&& rhs) {return lhs < rhs*4;} );
// Different closure type - compiler error! What do you copy from!?
There isn't any legal way to create a single object of the closure type of the first lambda. Therefore, even if said rule was to be removed, you couldn't create a single instance of my_map_type
. Similar problems occur with other "closure type as template argument" scenarios.
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