Skip to content

Commit 98c634c

Browse files
committed
[expr.prim.lambda] Split specification of lambda expressions into subsections.
Fixes #1155.
1 parent 2f6aff7 commit 98c634c

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
@@ -3634,7 +3634,7 @@
36343634
has all of the following properties:
36353635
\begin{itemize}
36363636
\item it has a trivial destructor,
3637-
\item it is either a closure type~(\ref{expr.prim.lambda}),
3637+
\item it is either a closure type~(\ref{expr.prim.lambda.closure}),
36383638
an aggregate type~(\ref{dcl.init.aggr}), or
36393639
has at least one constexpr constructor or constructor template
36403640
(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
@@ -601,45 +601,6 @@
601601
\terminal{[} lambda-capture\opt{} \terminal{]}
602602
\end{bnf}
603603

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

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

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

@@ -733,23 +684,6 @@
733684
An implementation shall not add members of rvalue reference type to the closure
734685
type.
735686

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

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

863+
\pnum
894864
The value returned by any given specialization of this conversion function
895865
template is the address of a function \tcode{F} that, when invoked, has the same
896866
effect as invoking the generic lambda's corresponding function call operator
@@ -910,6 +880,7 @@
910880
\end{codeblock}
911881
\end{example}
912882

883+
\pnum
913884
The conversion function or conversion function template is public,
914885
constexpr, non-virtual, non-explicit, const, and has a non-throwing exception
915886
specification~(\ref{except.spec}).
@@ -952,6 +923,70 @@
952923
the \grammarterm{compound-statement} of the \grammarterm{lambda-expression},
953924
with semantics as described in~\ref{dcl.fct.def.general}.
954925

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

1263-
\pnum
1264-
The closure type associated with a \grammarterm{lambda-expression} has no
1265-
default constructor and a deleted copy assignment operator. It has a
1266-
defaulted copy constructor and a defaulted move constructor~(\ref{class.copy}).
1267-
\begin{note} These special member functions are implicitly defined as
1268-
usual, and might therefore be defined as deleted. \end{note}
1269-
1270-
\pnum
1271-
The closure type associated with a \grammarterm{lambda-expression} has an
1272-
implicitly-declared destructor~(\ref{class.dtor}).
1273-
1274-
\pnum
1275-
A member of a closure type shall not be
1276-
explicitly instantiated~(\ref{temp.explicit}),
1277-
explicitly specialized~(\ref{temp.expl.spec}), or
1278-
named in a \tcode{friend} declaration~(\ref{class.friend}).
1279-
12801298
\pnum
12811299
When the \grammarterm{lambda-expression} is evaluated, the entities that are
12821300
captured by copy are used to direct-initialize each corresponding non-static data member
@@ -4981,7 +4999,7 @@
49814999
If the odr-use occurs in an invocation
49825000
of a function call operator of a closure type,
49835001
it no longer refers to \tcode{this} or to an enclosing automatic variable
4984-
due to the transformation~(\ref{expr.prim.lambda})
5002+
due to the transformation~(\ref{expr.prim.lambda.capture})
49855003
of the \grammarterm{id-expression} into
49865004
an access of the corresponding data member.
49875005
\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
@@ -146,7 +146,7 @@
146146
in a templated entity,
147147
\item a member of a templated entity,
148148
\item an enumerator for an enumeration that is a templated entity, or
149-
\item the closure type of a \grammarterm{lambda-expression}~(\ref{expr.prim.lambda})
149+
\item the closure type of a \grammarterm{lambda-expression}~(\ref{expr.prim.lambda.closure})
150150
appearing in the declaration of a templated entity.
151151
\end{itemize}
152152

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

0 commit comments

Comments
 (0)