Skip to content

Commit 743fcd7

Browse files
authored
Merge 2021-10 CWG Motion 8
P2036R3 Change scope of lambda trailing-return-type
2 parents 1fa5f70 + d9bcc38 commit 743fcd7

File tree

1 file changed

+41
-13
lines changed

1 file changed

+41
-13
lines changed

source/expressions.tex

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,21 +1443,34 @@
14431443
\pnum
14441444
The result is the entity denoted by
14451445
the \grammarterm{unqualified-id}\iref{basic.lookup.unqual}.
1446-
If the entity is a local entity\iref{basic.pre}
1447-
and naming it from outside of an unevaluated operand
1448-
within the scope where the \grammarterm{unqualified-id} appears
1449-
would result in some intervening \grammarterm{lambda-expression}
1450-
capturing it by copy\iref{expr.prim.lambda.capture},
1446+
If the \grammarterm{unqualified-id} appears
1447+
in a \grammarterm{lambda-expression} at program point $P$ and
1448+
the entity is a local entity\iref{basic.pre} or a variable declared by
1449+
an \grammarterm{init-capture}\iref{expr.prim.lambda.capture},
1450+
then let $S$ be the \grammarterm{compound-expression} of
1451+
the innermost enclosing \grammarterm{lambda-expression} of $P$.
1452+
If naming the entity from outside of an unevaluated operand within $S$
1453+
would refer to an entity
1454+
captured by copy in some intervening \grammarterm{lambda-expression},
1455+
then let $E$ be the innermost such \grammarterm{lambda-expression}, and:
1456+
\begin{itemize}
1457+
\item
1458+
If $P$ is in $E$'s function parameter scope
1459+
but not its \grammarterm{parameter-declaration-clause}, then
14511460
the type of the expression is
14521461
the type of a class member access expression\iref{expr.ref}
14531462
naming the non-static data member
14541463
that would be declared for such a capture
1455-
in the object parameter\iref{dcl.fct} of the function call operator of
1456-
the innermost such intervening \grammarterm{lambda-expression}.
1464+
in the object parameter\iref{dcl.fct} of the function call operator of $E$.
14571465
\begin{note}
1458-
If that \grammarterm{lambda-expression} is not declared \keyword{mutable},
1466+
If $E$ is not declared \keyword{mutable},
14591467
the type of such an identifier will typically be \keyword{const} qualified.
14601468
\end{note}
1469+
\item
1470+
Otherwise (if $P$ either precedes $E$'s function parameter scope or
1471+
is in $E$'s \grammarterm{parameter-declaration-clause}),
1472+
the program is ill-formed.
1473+
\end{itemize}
14611474
Otherwise, the type of the expression is the type of the result.
14621475
\begin{note}
14631476
If the entity is a template parameter object for
@@ -1477,12 +1490,24 @@
14771490
\begin{codeblock}
14781491
void f() {
14791492
float x, &r = x;
1480-
[=] {
1493+
[=]() -> decltype((x)) { // lambda returns \tcode{float const\&} because this lambda is not \tcode{mutable} and
1494+
// \tcode{x} is an lvalue
14811495
decltype(x) y1; // \tcode{y1} has type \tcode{float}
1482-
decltype((x)) y2 = y1; // \tcode{y2} has type \tcode{float const\&} because this lambda
1483-
// is not \keyword{mutable} and \tcode{x} is an lvalue
1496+
decltype((x)) y2 = y1; // \tcode{y2} has type \tcode{float const\&}
14841497
decltype(r) r1 = y1; // \tcode{r1} has type \tcode{float\&}
14851498
decltype((r)) r2 = y2; // \tcode{r2} has type \tcode{float const\&}
1499+
return y2;
1500+
};
1501+
1502+
[=]<decltype(x) P>{}; // error: \tcode{x} refers to local entity but precedes the
1503+
// lambda's function parameter scope
1504+
[=](decltype((x)) y){}; // error: \tcode{x} refers to local entity but is in the lambda's
1505+
// \grammarterm{parameter-declaration-clause}
1506+
[=]{
1507+
[]<decltype(x) P>{}; // OK, \tcode{x} is in the outer lambda's function parameter scope
1508+
[](decltype((x)) y){}; // OK, lambda takes a parameter of type \tcode{float const\&}
1509+
[x=1](decltype((x)) z){}; // error: \tcode{x} refers to \grammarterm{init-capture} but is in the lambda's
1510+
// \grammarterm{parameter-declaration-clause}
14861511
};
14871512
}
14881513
\end{codeblock}
@@ -2197,8 +2222,8 @@
21972222
\end{example}
21982223

21992224
\pnum
2200-
An \grammarterm{init-capture} inhabits the scope of
2201-
the \grammarterm{lambda-expression}'s \grammarterm{compound-statement}.
2225+
An \grammarterm{init-capture} inhabits the function parameter scope of
2226+
the \grammarterm{lambda-expression}'s \grammarterm{parameter-declaration-clause}.
22022227
An \grammarterm{init-capture} without ellipsis
22032228
behaves as if it declares and explicitly captures a variable of
22042229
the form ``\keyword{auto} \grammarterm{init-capture} \tcode{;}'', except that:
@@ -2224,6 +2249,9 @@
22242249
}(); // Updates \tcode{::x} to 6, and initializes \tcode{y} to 7.
22252250

22262251
auto z = [a = 42](int a) { return 1; }; // error: parameter and local variable have the same name
2252+
auto counter = [i=0]() mutable -> decltype(i) { // OK, returns \tcode{int}
2253+
return i++;
2254+
};
22272255
\end{codeblock}
22282256
\end{example}
22292257

0 commit comments

Comments
 (0)