Skip to content

Commit 39f8109

Browse files
committed
[expr.prim.lambda] Split specification of lambda expressions into subsections.
Fixes #1155.
1 parent 9a6d4c3 commit 39f8109

File tree

5 files changed

+135
-117
lines changed

5 files changed

+135
-117
lines changed

source/basic.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3629,7 +3629,7 @@
36293629
has all of the following properties:
36303630
\begin{itemize}
36313631
\item it has a trivial destructor,
3632-
\item it is either a closure type~(\ref{expr.prim.lambda}),
3632+
\item it is either a closure type~(\ref{expr.prim.lambda.closure}),
36333633
an aggregate type~(\ref{dcl.init.aggr}), or
36343634
has at least one constexpr constructor or constructor template
36353635
(possibly inherited~(\ref{namespace.udecl}) from a base class)

source/declarations.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,7 +1556,7 @@
15561556
from an initializer. The \tcode{auto}
15571557
\grammarterm{type-specifier} is also used to
15581558
introduce a function type having a \grammarterm{trailing-return-type} or to
1559-
signify that a lambda is a generic lambda (\ref{expr.prim.lambda}).
1559+
signify that a lambda is a generic lambda (\ref{expr.prim.lambda.closure}).
15601560
The \tcode{auto} \grammarterm{type-specifier} is also used to introduce a
15611561
decomposition declaration (\ref{dcl.decomp}).
15621562

@@ -1578,7 +1578,7 @@
15781578
\grammarterm{decl-specifier}{s} in the \grammarterm{decl-specifier-seq} of a
15791579
\grammarterm{parameter-declaration} of a \grammarterm{lambda-expression}, the
15801580
\indextext{generic lambda!definition of}%
1581-
lambda is a \term{generic lambda}~(\ref{expr.prim.lambda}). \begin{example}
1581+
lambda is a \term{generic lambda}~(\ref{expr.prim.lambda.closure}). \begin{example}
15821582
\begin{codeblock}
15831583
auto glambda = [](int i, auto a) { return i; }; // OK: a generic lambda
15841584
\end{codeblock}

source/expressions.tex

Lines changed: 129 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -599,45 +599,6 @@
599599
\terminal{[} lambda-capture\opt{} \terminal{]}
600600
\end{bnf}
601601

602-
\begin{bnf}
603-
\nontermdef{lambda-capture}\br
604-
capture-default\br
605-
capture-list\br
606-
capture-default \terminal{,} capture-list
607-
\end{bnf}
608-
609-
\begin{bnf}
610-
\nontermdef{capture-default}\br
611-
\terminal{\&}\br
612-
\terminal{=}
613-
\end{bnf}
614-
615-
\begin{bnf}
616-
\nontermdef{capture-list}\br
617-
capture \terminal{...\opt}\br
618-
capture-list \terminal{,} capture \terminal{...\opt}
619-
\end{bnf}
620-
621-
\begin{bnf}
622-
\nontermdef{capture}\br
623-
simple-capture\br
624-
init-capture
625-
\end{bnf}
626-
627-
\begin{bnf}
628-
\nontermdef{simple-capture}\br
629-
identifier\br
630-
\terminal{\&} identifier\br
631-
\terminal{this}\br
632-
\terminal{* this}
633-
\end{bnf}
634-
635-
\begin{bnf}
636-
\nontermdef{init-capture}\br
637-
identifier initializer\br
638-
\terminal{\&} identifier initializer
639-
\end{bnf}
640-
641602
\begin{bnf}
642603
\nontermdef{lambda-declarator}\br
643604
\terminal{(} parameter-declaration-clause \terminal{)} decl-specifier-seq\opt\br
@@ -656,37 +617,6 @@
656617
\end{codeblock}
657618
\end{example}
658619

659-
\pnum
660-
In the \grammarterm{decl-specifier-seq} of the \grammarterm{lambda-declarator},
661-
each \grammarterm{decl-specifier}
662-
shall either be \tcode{mutable} or \tcode{constexpr}.
663-
\begin{example}
664-
\begin{codeblock}
665-
auto monoid = [](auto v) { return [=] { return v; }; };
666-
auto add = [](auto m1) constexpr {
667-
auto ret = m1();
668-
return [=](auto m2) mutable {
669-
auto m1val = m1();
670-
auto plus = [=](auto m2val) mutable constexpr
671-
{ return m1val += m2val; };
672-
ret = plus(m2());
673-
return monoid(ret);
674-
};
675-
};
676-
constexpr auto zero = monoid(0);
677-
constexpr auto one = monoid(1);
678-
static_assert(add(one)(zero)() == one()); // OK
679-
680-
// Since \tcode{two} below is not declared \tcode{constexpr}, an evaluation of its \tcode{constexpr} member function call operator
681-
// cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture)
682-
// in a constant expression.
683-
auto two = monoid(2);
684-
assert(two() == 2); // OK, not a constant expression.
685-
static_assert(add(one)(one)() == two()); // ill-formed: \tcode{two()} is not a constant expression
686-
static_assert(add(one)(one)() == monoid(2)()); // OK
687-
\end{codeblock}
688-
\end{example}
689-
690620
\pnum
691621
A \grammarterm{lambda-expression} is a prvalue
692622
whose result object is called the \defn{closure object}. A
@@ -703,17 +633,38 @@
703633
object~(\ref{function.objects}).\end{note}
704634

705635
\pnum
706-
The type of the \grammarterm{lambda-expression} (which is also the type of the
707-
closure object) is a unique, unnamed non-union class type
708-
--- called the \defn{closure type} ---
636+
If a \grammarterm{lambda-expression} does not include a
637+
\grammarterm{lambda-declarator}, it is as if the \grammarterm{lambda-declarator} were
638+
\tcode{()}.
639+
The lambda return type is \tcode{auto}, which is replaced by the
640+
type specified by the
641+
\grammarterm{trailing-return-type} if provided and/or deduced from
642+
\tcode{return} statements as described in~\ref{dcl.spec.auto}.
643+
\begin{example}
644+
\begin{codeblock}
645+
auto x1 = [](int i){ return i; }; // OK: return type is \tcode{int}
646+
auto x2 = []{ return { 1, 2 }; }; // error: deducing return type from \grammarterm{braced-init-list}
647+
int j;
648+
auto x3 = []()->auto&& { return j; }; // OK: return type is \tcode{int\&}
649+
\end{codeblock}
650+
\end{example}
651+
652+
\rSec3[expr.prim.lambda.closure]{Closure types}%
653+
654+
\pnum
655+
The type of a \grammarterm{lambda-expression} (which is also the type of the
656+
closure object) is a unique, unnamed non-union class type,
657+
called the \defn{closure type},
709658
whose properties are described below.
710-
This class type is not an aggregate type~(\ref{dcl.init.aggr}).
659+
660+
\pnum
711661
The closure type is declared in the smallest block
712662
scope, class scope, or namespace scope that contains the corresponding
713663
\grammarterm{lambda-expression}. \begin{note} This determines the set of namespaces and
714664
classes associated with the closure type~(\ref{basic.lookup.argdep}). The parameter
715665
types of a \grammarterm{lambda-declarator} do not affect these associated namespaces and
716-
classes. \end{note} An implementation may define the closure type differently from what
666+
classes. \end{note} The closure type is not an aggregate type~(\ref{dcl.init.aggr}).
667+
An implementation may define the closure type differently from what
717668
is described below provided this does not alter the observable behavior of the program
718669
other than by changing:
719670

@@ -731,23 +682,6 @@
731682
An implementation shall not add members of rvalue reference type to the closure
732683
type.
733684

734-
\pnum
735-
If a \grammarterm{lambda-expression} does not include a
736-
\grammarterm{lambda-declarator}, it is as if the \grammarterm{lambda-declarator} were
737-
\tcode{()}.
738-
The lambda return type is \tcode{auto}, which is replaced by the
739-
type specified by the
740-
\grammarterm{trailing-return-type} if provided and/or deduced from
741-
\tcode{return} statements as described in~\ref{dcl.spec.auto}.
742-
\begin{example}
743-
\begin{codeblock}
744-
auto x1 = [](int i){ return i; }; // OK: return type is \tcode{int}
745-
auto x2 = []{ return { 1, 2 }; }; // error: deducing return type from \grammarterm{braced-init-list}
746-
int j;
747-
auto x3 = []()->auto&& { return j; }; // OK: return type is \tcode{int\&}
748-
\end{codeblock}
749-
\end{example}
750-
751685
\pnum
752686
The closure type for a non-generic \grammarterm{lambda-expression} has a public
753687
inline function call operator~(\ref{over.call}) whose parameters and return type
@@ -788,7 +722,12 @@
788722
q(); // OK: outputs \tcode{1a3.14}
789723
\end{codeblock}
790724
\end{example}
791-
This function call operator or operator template is declared
725+
726+
\pnum
727+
In the \grammarterm{decl-specifier-seq} of the \grammarterm{lambda-declarator},
728+
each \grammarterm{decl-specifier}
729+
shall either be \tcode{mutable} or \tcode{constexpr}.
730+
The function call operator or operator template is declared
792731
\tcode{const}~(\ref{class.mfct.non-static}) if and only if the
793732
\grammarterm{lambda-expression}'s \grammarterm{parameter-declaration-clause} is not
794733
followed by \tcode{mutable}. It is neither virtual nor declared \tcode{volatile}. Any
@@ -817,6 +756,34 @@
817756
\end{codeblock}
818757
\end{example}
819758

759+
\pnum
760+
\begin{example}
761+
\begin{codeblock}
762+
auto monoid = [](auto v) { return [=] { return v; }; };
763+
auto add = [](auto m1) constexpr {
764+
auto ret = m1();
765+
return [=](auto m2) mutable {
766+
auto m1val = m1();
767+
auto plus = [=](auto m2val) mutable constexpr
768+
{ return m1val += m2val; };
769+
ret = plus(m2());
770+
return monoid(ret);
771+
};
772+
};
773+
constexpr auto zero = monoid(0);
774+
constexpr auto one = monoid(1);
775+
static_assert(add(one)(zero)() == one()); // OK
776+
777+
// Since \tcode{two} below is not declared \tcode{constexpr}, an evaluation of its \tcode{constexpr} member function call operator
778+
// cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture)
779+
// in a constant expression.
780+
auto two = monoid(2);
781+
assert(two() == 2); // OK, not a constant expression.
782+
static_assert(add(one)(one)() == two()); // ill-formed: \tcode{two()} is not a constant expression
783+
static_assert(add(one)(one)() == monoid(2)()); // OK
784+
\end{codeblock}
785+
\end{example}
786+
820787
\pnum
821788
The closure type for a non-generic \grammarterm{lambda-expression} with no
822789
\grammarterm{lambda-capture}
@@ -839,6 +806,8 @@
839806
the pointer to function shall behave as if it were a
840807
\grammarterm{decltype-specifier} denoting the return type of the corresponding
841808
function call operator template specialization.
809+
810+
\pnum
842811
\begin{note}
843812
If the generic lambda has no \grammarterm{trailing-return-type} or
844813
the \grammarterm{trailing-return-type} contains a placeholder type, return type
@@ -889,6 +858,7 @@
889858
\end{codeblock}
890859
\end{example}
891860

861+
\pnum
892862
The value returned by any given specialization of this conversion function
893863
template is the address of a function \tcode{F} that, when invoked, has the same
894864
effect as invoking the generic lambda's corresponding function call operator
@@ -908,6 +878,7 @@
908878
\end{codeblock}
909879
\end{example}
910880

881+
\pnum
911882
The conversion function or conversion function template is public,
912883
constexpr, non-virtual, non-explicit, const, and has a non-throwing exception
913884
specification~(\ref{except.spec}).
@@ -950,6 +921,70 @@
950921
the \grammarterm{compound-statement} of the \grammarterm{lambda-expression},
951922
with semantics as described in~\ref{dcl.fct.def.general}.
952923

924+
\pnum
925+
The closure type associated with a \grammarterm{lambda-expression} has no
926+
default constructor and a deleted copy assignment operator. It has a
927+
defaulted copy constructor and a defaulted move constructor~(\ref{class.copy}).
928+
\begin{note} These special member functions are implicitly defined as
929+
usual, and might therefore be defined as deleted. \end{note}
930+
931+
\pnum
932+
The closure type associated with a \grammarterm{lambda-expression} has an
933+
implicitly-declared destructor~(\ref{class.dtor}).
934+
935+
\pnum
936+
A member of a closure type shall not be
937+
explicitly instantiated~(\ref{temp.explicit}),
938+
explicitly specialized~(\ref{temp.expl.spec}), or
939+
named in a \tcode{friend} declaration~(\ref{class.friend}).
940+
941+
\rSec3[expr.prim.lambda.capture]{Captures}%
942+
943+
\begin{bnf}
944+
\nontermdef{lambda-capture}\br
945+
capture-default\br
946+
capture-list\br
947+
capture-default \terminal{,} capture-list
948+
\end{bnf}
949+
950+
\begin{bnf}
951+
\nontermdef{capture-default}\br
952+
\terminal{\&}\br
953+
\terminal{=}
954+
\end{bnf}
955+
956+
\begin{bnf}
957+
\nontermdef{capture-list}\br
958+
capture \terminal{...\opt}\br
959+
capture-list \terminal{,} capture \terminal{...\opt}
960+
\end{bnf}
961+
962+
\begin{bnf}
963+
\nontermdef{capture}\br
964+
simple-capture\br
965+
init-capture
966+
\end{bnf}
967+
968+
\begin{bnf}
969+
\nontermdef{simple-capture}\br
970+
identifier\br
971+
\terminal{\&} identifier\br
972+
\terminal{this}\br
973+
\terminal{* this}
974+
\end{bnf}
975+
976+
\begin{bnf}
977+
\nontermdef{init-capture}\br
978+
identifier initializer\br
979+
\terminal{\&} identifier initializer
980+
\end{bnf}
981+
982+
\pnum
983+
The body of a \grammarterm{lambda-expression} may refer to variables
984+
with automatic storage duration and the \tcode{*this} object (if any)
985+
of enclosing block scopes by capturing those entities, as described
986+
below.
987+
953988
\pnum
954989
If a \grammarterm{lambda-capture} includes a \grammarterm{capture-default} that
955990
is \tcode{\&}, no identifier in a \grammarterm{simple-capture} of that
@@ -1258,23 +1293,6 @@
12581293
\end{codeblock}
12591294
\end{example}
12601295

1261-
\pnum
1262-
The closure type associated with a \grammarterm{lambda-expression} has no
1263-
default constructor and a deleted copy assignment operator. It has a
1264-
defaulted copy constructor and a defaulted move constructor~(\ref{class.copy}).
1265-
\begin{note} These special member functions are implicitly defined as
1266-
usual, and might therefore be defined as deleted. \end{note}
1267-
1268-
\pnum
1269-
The closure type associated with a \grammarterm{lambda-expression} has an
1270-
implicitly-declared destructor~(\ref{class.dtor}).
1271-
1272-
\pnum
1273-
A member of a closure type shall not be
1274-
explicitly instantiated~(\ref{temp.explicit}),
1275-
explicitly specialized~(\ref{temp.expl.spec}), or
1276-
named in a \tcode{friend} declaration~(\ref{class.friend}).
1277-
12781296
\pnum
12791297
When the \grammarterm{lambda-expression} is evaluated, the entities that are
12801298
captured by copy are used to direct-initialize each corresponding non-static data member
@@ -4978,7 +4996,7 @@
49784996
If the odr-use occurs in an invocation
49794997
of a function call operator of a closure type,
49804998
it no longer refers to \tcode{this} or to an enclosing automatic variable
4981-
due to the transformation~(\ref{expr.prim.lambda})
4999+
due to the transformation~(\ref{expr.prim.lambda.capture})
49825000
of the \grammarterm{id-expression} into
49835001
an access of the corresponding data member.
49845002
\begin{example}

source/special.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@
518518
The first context is when a default constructor is called to initialize
519519
an element of an array with no corresponding initializer~(\ref{dcl.init}).
520520
The second context is when a copy constructor is called to copy an element of
521-
an array while the entire array is copied~(\ref{expr.prim.lambda},~\ref{class.copy}).
521+
an array while the entire array is copied~(\ref{expr.prim.lambda.capture},~\ref{class.copy}).
522522
In either case, if the constructor has one or more default arguments,
523523
the destruction of every temporary created in a default argument is
524524
sequenced before the construction of the next array element, if any.

source/templates.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@
148148
in a templated entity,
149149
\item a member of a templated entity,
150150
\item an enumerator for an enumeration that is a templated entity, or
151-
\item the closure type of a \grammarterm{lambda-expression}~(\ref{expr.prim.lambda})
151+
\item the closure type of a \grammarterm{lambda-expression}~(\ref{expr.prim.lambda.closure})
152152
appearing in the declaration of a templated entity.
153153
\end{itemize}
154154

@@ -4798,7 +4798,7 @@
47984798
the same template parameters and the same access as that of the function template
47994799
\tcode{f}
48004800
used at that point, except that the scope in which a closure type is
4801-
declared~(\ref{expr.prim.lambda}) -- and therefore its associated namespaces --
4801+
declared~(\ref{expr.prim.lambda.closure}) -- and therefore its associated namespaces --
48024802
remain as determined from the context of the definition for the default
48034803
argument.
48044804
This analysis is called

0 commit comments

Comments
 (0)