Why are lambda expressions not allowed in unvalued operands but allowed in unvalued parts of constant expressions?

If we look at the draft draft C ++ 5.1.2 lambda expressions in paragraph 2 say (emphasis mine forward):

Evaluation of a lambda expression leads to a temporary assignment (12.2). This temporary is called a closing object. A lambda expression should not appear in an unpublished operand (section 5). [Note. The closing object behaves like a function object (20.8) .- End note]

and section 5.19 The constant expressions given in paragraph 2 say:

A conditional expression is an expression of a basic constant if it does not include one of the following: a potentially evaluated subexpression (3.2), but a subexpression of logical AND (5.14), logical OR (5.15), and conditional (5.16) operations that are not evaluated, are not are considered [...]

and has the following brand:

- lambda expression (5.1.2);

So why are lambdas expressions not allowed in the unvalued operand but allowed in the unvalued parts of constant expressions?

I see how for inexperienced operands type information in several cases ( decltype or typeid ) is not very useful, since each lambda has a unique type. Although why do we want to resolve them in an invaluable context of constant expression, is it unclear, perhaps, for SFINAE ?

+9
c ++ lambda c ++ 11 c ++ 14 constant-expression
Mar 6 '14 at 17:49
source share
1 answer

The main reason for excluding non-oriented operands is given in the Reports and accepted errors of the standard kernel in C ++ # 1607. Lambdas in the parameters of the template , which tries to clarify this restriction and states that the purpose of the restriction in section 5.1.2 was as follows:

[...] prevent the need to deal with them in function template signatures [...]

As the documentation of the issue, the current edition actually has a hole, because constant expressions allow them in an invaluable context. But it does not say the validity of this limitation. The desire to avoid the deletion of the name stands out, and you can conclude that avoiding the SFINAE extension was also desirable as the proposed resolution aims to tighten the restriction, although some viable alternatives would allow SFINAE. A modified version of paragraph 5.1.2 2:

A lambda expression should not appear in an unpublished operand (section 5 [expr]), in a template argument in an alias declaration in a typedef declaration, or in a function or function declaration outside its function body and default arguments [Note. The goal is to prevent lambda from appearing in the signature signature note] . [Note. A closure object behaves like a function object (20.10 [function.objects]). -end note]

This offer has been accepted and is located in N3936 ( see this answer for reference )

For a more explicit discussion of rationale, to avoid having lambda as an unvalued operand. A discussion titled Justification for lambda expressions that are not allowed in unappreciated contexts on comp.lang.cpp.moderated Daniel Krugler outlines three reasons:

  • Extreme extension of possible SFINAE :

    [...] The reason they were excluded is explained by this extreme extension of sfinae cases (you opened the Pandora box for the compiler) [...]

  • In many cases, this is simply useless, since each lambda has a unique type, a hypothetical example:

     template<typename T, typename U> void g(T, U, decltype([](T x, T y) { return x + y; }) func); g(1, 2, [](int x, int y) { return x + y; }); 

    The type of lambda in the declaration and the call are different (by definition), and therefore this cannot work.

  • The name mangling also becomes a problem, because as soon as you enable lambda in the function signature, the lambda bodies will have to be mutilated. This means that you come up with rules to cripple all possible statements, which would be burdensome for at least some implementations.

+13
Mar 6 '14 at 17:49
source share



All Articles