|
635 | 635 |
|
636 | 636 | \begin{bnf}
|
637 | 637 | \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 |
639 | 639 | \hspace*{\bnfindentinc}exception-specification\opt attribute-specifier-seq\opt trailing-return-type\opt
|
640 | 640 | \end{bnf}
|
641 | 641 |
|
| 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 | + |
642 | 673 | \pnum
|
643 | 674 | The evaluation of a \grammarterm{lambda-expression} results in a prvalue
|
644 | 675 | temporary~(\ref{class.temporary}). This temporary is called the \defn{closure object}. A
|
|
656 | 687 |
|
657 | 688 | \pnum
|
658 | 689 | 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}). |
662 | 694 | The closure type is declared in the smallest block
|
663 | 695 | scope, class scope, or namespace scope that contains the corresponding
|
664 | 696 | \grammarterm{lambda-expression}. \enternote This determines the set of namespaces and
|
|
746 | 778 | applies to the corresponding function call operator or operator template.
|
747 | 779 | An \grammarterm{attribute-specifier-seq} in a \grammarterm{lambda-declarator} appertains
|
748 | 780 | 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}). |
749 | 786 | \enternote Names referenced in
|
750 | 787 | the \grammarterm{lambda-declarator} are looked up in the context in which the
|
751 | 788 | \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 |
752 | 801 |
|
753 | 802 | \pnum
|
754 | 803 | The closure type for a non-generic \grammarterm{lambda-expression} with no
|
|
759 | 808 | The conversion is to ``pointer to \tcode{noexcept} function''
|
760 | 809 | if the function call operator
|
761 | 810 | 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. |
765 | 816 | For a generic lambda with no \grammarterm{lambda-capture}, the closure type has a
|
766 | 817 | conversion function template to
|
767 | 818 | pointer to function. The conversion function template has the same invented
|
|
770 | 821 | the pointer to function shall behave as if it were a
|
771 | 822 | \grammarterm{decltype-specifier} denoting the return type of the corresponding
|
772 | 823 | 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 |
774 | 826 | the \grammarterm{trailing-return-type} contains a placeholder type, return type
|
775 | 827 | deduction of the corresponding function call operator template specialization
|
776 | 828 | has to be done. The corresponding specialization is that instantiation of the
|
|
798 | 850 | };
|
799 | 851 | \end{codeblock}
|
800 | 852 | \exitnote
|
| 853 | + |
801 | 854 | \enterexample
|
802 | 855 | \begin{codeblock}
|
803 | 856 | void f1(int (*)(int)) { }
|
|
817 | 870 | int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK
|
818 | 871 | \end{codeblock}
|
819 | 872 | \exitexample
|
| 873 | + |
820 | 874 | 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 |
822 | 876 | effect as invoking the generic lambda's corresponding function call operator
|
823 | 877 | template specialization.
|
| 878 | +\tcode{F} is a constexpr function |
| 879 | +if the corresponding specialization is a constexpr function. |
824 | 880 | \enternote
|
825 | 881 | This will result in the implicit instantiation of the generic lambda's body.
|
826 | 882 | The instantiated generic lambda's return type and parameter types shall match
|
|
833 | 889 | GL_int(3); // OK: same as \tcode{GL(3)}
|
834 | 890 | \end{codeblock}
|
835 | 891 | \exitexample
|
| 892 | + |
836 | 893 | 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 |
838 | 895 | 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 |
839 | 908 |
|
840 | 909 | \pnum
|
841 | 910 | The \grammarterm{lambda-expression}'s \grammarterm{compound-statement} yields the
|
|
1052 | 1121 | An entity is \defnx{captured by reference}{captured!by~reference} if it is implicitly or explicitly
|
1053 | 1122 | captured but not captured by copy. It is unspecified whether additional unnamed
|
1054 | 1123 | 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. |
1056 | 1133 |
|
1057 | 1134 | \pnum
|
1058 | 1135 | If a \grammarterm{lambda-expression} \tcode{m2} captures an entity and that entity is
|
|
4750 | 4827 | zero~(\ref{expr.mul}), or certain shift operations~(\ref{expr.shift})
|
4751 | 4828 | \exitnote;
|
4752 | 4829 |
|
4753 |
| -\item |
4754 |
| -a \grammarterm{lambda-expression}~(\ref{expr.prim.lambda}); |
4755 |
| - |
4756 | 4830 | \item
|
4757 | 4831 | an lvalue-to-rvalue conversion~(\ref{conv.lval}) unless
|
4758 | 4832 | it is applied to
|
|
4802 | 4876 | automatic storage duration defined outside that
|
4803 | 4877 | \grammarterm{lambda-expression}, where
|
4804 | 4878 | 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 |
4805 | 4909 |
|
4806 | 4910 | \item
|
4807 | 4911 | a conversion from type \cv{} \tcode{void *} to a pointer-to-object type;
|
|
0 commit comments