Skip to content

Commit b17b806

Browse files
committed
Merge 2016-02 CWG Motion 7
2 parents b82546b + 7dcae6f commit b17b806

File tree

3 files changed

+123
-18
lines changed

3 files changed

+123
-18
lines changed

source/basic.tex

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3636,8 +3636,9 @@
36363636
has all of the following properties:
36373637
\begin{itemize}
36383638
\item it has a trivial destructor,
3639-
\item it is an aggregate type~(\ref{dcl.init.aggr}) or has
3640-
at least one \tcode{constexpr} constructor or constructor template
3639+
\item it is either a closure type~(\ref{expr.prim.lambda}),
3640+
an aggregate type~(\ref{dcl.init.aggr}), or
3641+
has at least one \tcode{constexpr} constructor or constructor template
36413642
(possibly inherited~(\ref{namespace.udecl}) from a base class)
36423643
that is not a copy or move constructor,
36433644
\item if it is a union, at least one of its non-static data members is

source/declarations.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,8 @@
254254
same type.
255255

256256
\pnum
257-
Each \grammarterm{decl-specifier} shall appear at most once in the complete
258-
\grammarterm{decl-specifier-seq} of a declaration, except that
257+
Each \grammarterm{decl-specifier} shall appear at most once in a complete
258+
\grammarterm{decl-specifier-seq}, except that
259259
\tcode{long} may appear twice.
260260

261261
\pnum

source/expressions.tex

Lines changed: 118 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -635,10 +635,41 @@
635635

636636
\begin{bnf}
637637
\nontermdef{lambda-declarator}\br
638-
\terminal{(} parameter-declaration-clause \terminal{)} \terminal{mutable}\opt\br
638+
\terminal{(} parameter-declaration-clause \terminal{)} decl-specifier-seq\opt\br
639639
\hspace*{\bnfindentinc}exception-specification\opt attribute-specifier-seq\opt trailing-return-type\opt
640640
\end{bnf}
641641

642+
\pnum
643+
In the \grammarterm{decl-specifier-seq} of the \grammarterm{lambda-declarator},
644+
each \grammarterm{decl-specifier}
645+
shall either be \tcode{mutable} or \tcode{constexpr}.
646+
\enterexample
647+
\begin{codeblock}
648+
auto monoid = [](auto v) { return [=] { return v; }; };
649+
auto add = [](auto m1) constexpr {
650+
auto ret = m1();
651+
return [=](auto m2) mutable {
652+
auto m1val = m1();
653+
auto plus = [=](auto m2val) mutable constexpr
654+
{ return m1val += m2val; };
655+
ret = plus(m2());
656+
return monoid(ret);
657+
};
658+
};
659+
constexpr auto zero = monoid(0);
660+
constexpr auto one = monoid(1);
661+
static_assert(add(one)(zero)() == one()); // OK
662+
663+
// Since \tcode{two} below is not declared \tcode{constexpr}, an evaluation of its \tcode{constexpr} member function call operator
664+
// cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture)
665+
// in a constant expression.
666+
auto two = monoid(2);
667+
assert(two() == 2); // OK, not a constant expression.
668+
static_assert(add(one)(one)() == two()); // ill-formed: \tcode{two()} is not a constant expression
669+
static_assert(add(one)(one)() == monoid(2)()); // OK
670+
\end{codeblock}
671+
\exitexample
672+
642673
\pnum
643674
The evaluation of a \grammarterm{lambda-expression} results in a prvalue
644675
temporary~(\ref{class.temporary}). This temporary is called the \defn{closure object}. A
@@ -656,9 +687,10 @@
656687

657688
\pnum
658689
The type of the \grammarterm{lambda-expression} (which is also the type of the
659-
closure object) is a unique, unnamed non-union class type --- called the \defn{closure
660-
type} --- whose properties are described below. This class type is neither an
661-
aggregate~(\ref{dcl.init.aggr}) nor a literal type~(\ref{basic.types}).
690+
closure object) is a unique, unnamed non-union class type
691+
--- called the \defn{closure type} ---
692+
whose properties are described below.
693+
This class type is not an aggregate type~(\ref{dcl.init.aggr}).
662694
The closure type is declared in the smallest block
663695
scope, class scope, or namespace scope that contains the corresponding
664696
\grammarterm{lambda-expression}. \enternote This determines the set of namespaces and
@@ -746,9 +778,26 @@
746778
applies to the corresponding function call operator or operator template.
747779
An \grammarterm{attribute-specifier-seq} in a \grammarterm{lambda-declarator} appertains
748780
to the type of the corresponding function call operator or operator template.
781+
The function call operator or any given operator template specialization
782+
is a constexpr function if either
783+
the corresponding \grammarterm{lambda-expression}{'s}
784+
\grammarterm{parameter-declaration-clause} is followed by \tcode{constexpr}, or
785+
it satisfies the requirements for a constexpr function~(\ref{dcl.constexpr}).
749786
\enternote Names referenced in
750787
the \grammarterm{lambda-declarator} are looked up in the context in which the
751788
\grammarterm{lambda-expression} appears. \exitnote
789+
\enterexample
790+
\begin{codeblock}
791+
auto ID = [](auto a) { return a; };
792+
static_assert(ID(3) == 3); // OK
793+
794+
struct NonLiteral {
795+
NonLiteral(int n) : n(n) { }
796+
int n;
797+
};
798+
static_assert(ID(NonLiteral{3}).n == 3); // ill-formed
799+
\end{codeblock}
800+
\exitexample
752801

753802
\pnum
754803
The closure type for a non-generic \grammarterm{lambda-expression} with no
@@ -759,9 +808,11 @@
759808
The conversion is to ``pointer to \tcode{noexcept} function''
760809
if the function call operator
761810
has a non-throwing exception specification.
762-
The
763-
value returned by this conversion function shall be the address of a function that, when
764-
invoked, has the same effect as invoking the closure type's function call operator.
811+
The value returned by this conversion function
812+
is the address of a function \tcode{F} that, when invoked,
813+
has the same effect as invoking the closure type's function call operator.
814+
\tcode{F} is a constexpr function
815+
if the function call operator is a constexpr function.
765816
For a generic lambda with no \grammarterm{lambda-capture}, the closure type has a
766817
conversion function template to
767818
pointer to function. The conversion function template has the same invented
@@ -770,7 +821,8 @@
770821
the pointer to function shall behave as if it were a
771822
\grammarterm{decltype-specifier} denoting the return type of the corresponding
772823
function call operator template specialization.
773-
\enternote If the generic lambda has no \grammarterm{trailing-return-type} or
824+
\enternote
825+
If the generic lambda has no \grammarterm{trailing-return-type} or
774826
the \grammarterm{trailing-return-type} contains a placeholder type, return type
775827
deduction of the corresponding function call operator template specialization
776828
has to be done. The corresponding specialization is that instantiation of the
@@ -798,6 +850,7 @@
798850
};
799851
\end{codeblock}
800852
\exitnote
853+
801854
\enterexample
802855
\begin{codeblock}
803856
void f1(int (*)(int)) { }
@@ -817,10 +870,13 @@
817870
int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK
818871
\end{codeblock}
819872
\exitexample
873+
820874
The value returned by any given specialization of this conversion function
821-
template shall be the address of a function that, when invoked, has the same
875+
template is the address of a function \tcode{F} that, when invoked, has the same
822876
effect as invoking the generic lambda's corresponding function call operator
823877
template specialization.
878+
\tcode{F} is a constexpr function
879+
if the corresponding specialization is a constexpr function.
824880
\enternote
825881
This will result in the implicit instantiation of the generic lambda's body.
826882
The instantiated generic lambda's return type and parameter types shall match
@@ -833,9 +889,22 @@
833889
GL_int(3); // OK: same as \tcode{GL(3)}
834890
\end{codeblock}
835891
\exitexample
892+
836893
The conversion function or conversion function template is public,
837-
non-virtual, non-explicit, const, and has a non-throwing exception
894+
constexpr, non-virtual, non-explicit, const, and has a non-throwing exception
838895
specification~(\ref{except.spec}).
896+
\enterexample
897+
\begin{codeblock}
898+
auto Fwd = [](int (*fp)(int), auto a) { return fp(a); };
899+
auto C = [](auto a) { return a; };
900+
901+
static_assert(Fwd(C,3) == 3); // OK
902+
903+
// No specialization of the function call operator template can be constexpr (due to the local static).
904+
auto NC = [](auto a) { static int s; return a; };
905+
static_assert(Fwd(NC,3) == 3); // ill-formed
906+
\end{codeblock}
907+
\exitexample
839908

840909
\pnum
841910
The \grammarterm{lambda-expression}'s \grammarterm{compound-statement} yields the
@@ -1052,7 +1121,15 @@
10521121
An entity is \defnx{captured by reference}{captured!by~reference} if it is implicitly or explicitly
10531122
captured but not captured by copy. It is unspecified whether additional unnamed
10541123
non-static data members are declared in the closure type for entities captured by
1055-
reference. A member of an anonymous union shall not be captured by reference.
1124+
reference.
1125+
If declared, such non-static data members shall be of literal type.
1126+
\enterexample
1127+
\begin{codeblock}
1128+
// The inner closure type must be a literal type regardless of how reference captures are represented.
1129+
static_assert([](int n) { return [&n] { return ++n; }(); }(3) == 4);
1130+
\end{codeblock}
1131+
\exitexample
1132+
A member of an anonymous union shall not be captured by reference.
10561133

10571134
\pnum
10581135
If a \grammarterm{lambda-expression} \tcode{m2} captures an entity and that entity is
@@ -4750,9 +4827,6 @@
47504827
zero~(\ref{expr.mul}), or certain shift operations~(\ref{expr.shift})
47514828
\exitnote;
47524829

4753-
\item
4754-
a \grammarterm{lambda-expression}~(\ref{expr.prim.lambda});
4755-
47564830
\item
47574831
an lvalue-to-rvalue conversion~(\ref{conv.lval}) unless
47584832
it is applied to
@@ -4802,6 +4876,36 @@
48024876
automatic storage duration defined outside that
48034877
\grammarterm{lambda-expression}, where
48044878
the reference would be an odr-use~(\ref{basic.def.odr}, \ref{expr.prim.lambda});
4879+
\enterexample
4880+
\begin{codeblock}
4881+
void g() {
4882+
const int n = 0;
4883+
[=] {
4884+
constexpr int i = n; // OK, \tcode{n} is not odr-used and not captured here
4885+
constexpr int j = *&n; // ill-formed, \tcode{\&n} would be an odr-use of \tcode{n}
4886+
};
4887+
}
4888+
\end{codeblock}
4889+
\exitexample
4890+
\enternote
4891+
If the odr-use occurs in an invocation
4892+
of a function call operator of a closure type,
4893+
it no longer refers to \tcode{this} or to an enclosing automatic variable
4894+
due to the transformation~(\ref{expr.prim.lambda})
4895+
of the \grammarterm{id-expression} into
4896+
an access of the corresponding data member.
4897+
\enterexample
4898+
\begin{codeblock}
4899+
auto monad = [](auto v) { return [=] { return v; }; };
4900+
auto bind = [](auto m) {
4901+
return [=](auto fvm) { return fvm(m()); };
4902+
};
4903+
4904+
// OK to have captures to automatic objects created during constant expression evaluation.
4905+
static_assert(bind(monad(2))(monad)() == monad(2)());
4906+
\end{codeblock}
4907+
\exitexample
4908+
\exitnote
48054909

48064910
\item
48074911
a conversion from type \cv{} \tcode{void *} to a pointer-to-object type;

0 commit comments

Comments
 (0)