|
631 | 631 |
|
632 | 632 | \begin{bnf}
|
633 | 633 | \nontermdef{lambda-declarator}\br
|
634 |
| - \terminal{(} parameter-declaration-clause \terminal{)} \terminal{mutable}\opt\br |
| 634 | + \terminal{(} parameter-declaration-clause \terminal{)} decl-specifier-seq\opt\br |
635 | 635 | \hspace*{\bnfindentinc}exception-specification\opt attribute-specifier-seq\opt trailing-return-type\opt
|
636 | 636 | \end{bnf}
|
637 | 637 |
|
| 638 | +\pnum |
| 639 | +In the \grammarterm{decl-specifier-seq} of the \grammarterm{lambda-declarator}, |
| 640 | +each \grammarterm{decl-specifier} |
| 641 | +shall either be \tcode{mutable} or \tcode{constexpr}. |
| 642 | +\enterexample |
| 643 | +\begin{codeblock} |
| 644 | +auto monoid = [](auto v) { return [=] { return v; }; }; |
| 645 | +auto add = [](auto m1) constexpr { |
| 646 | + auto ret = m1(); |
| 647 | + return [=](auto m2) mutable { |
| 648 | + auto m1val = m1(); |
| 649 | + auto plus = [=](auto m2val) mutable constexpr |
| 650 | + { return m1val += m2val; }; |
| 651 | + ret = plus(m2()); |
| 652 | + return monoid(ret); |
| 653 | + }; |
| 654 | +}; |
| 655 | +constexpr auto zero = monoid(0); |
| 656 | +constexpr auto one = monoid(1); |
| 657 | +static_assert(add(one)(zero)() == one()); // OK |
| 658 | + |
| 659 | +// Since \tcode{two} below is not declared \tcode{constexpr}, an evaluation of its \tcode{constexpr} member function call operator |
| 660 | +// cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture) |
| 661 | +// in a constant expression. |
| 662 | +auto two = monoid(2); |
| 663 | +assert(two() == 2); // OK, not a constant expression. |
| 664 | +static_assert(add(one)(one)() == two()); // ill-formed: \tcode{two()} is not a constant expression |
| 665 | +static_assert(add(one)(one)() == monoid(2)()); // OK |
| 666 | +\end{codeblock} |
| 667 | +\exitexample |
| 668 | + |
638 | 669 | \pnum
|
639 | 670 | The evaluation of a \grammarterm{lambda-expression} results in a prvalue
|
640 | 671 | temporary~(\ref{class.temporary}). This temporary is called the \defn{closure object}. A
|
|
652 | 683 |
|
653 | 684 | \pnum
|
654 | 685 | The type of the \grammarterm{lambda-expression} (which is also the type of the
|
655 |
| -closure object) is a unique, unnamed non-union class type --- called the \defn{closure |
656 |
| -type} --- whose properties are described below. This class type is neither an |
657 |
| -aggregate~(\ref{dcl.init.aggr}) nor a literal type~(\ref{basic.types}). |
| 686 | +closure object) is a unique, unnamed non-union class type |
| 687 | +--- called the \defn{closure type} --- |
| 688 | +whose properties are described below. |
| 689 | +This class type is not an aggregate type~(\ref{dcl.init.aggr}). |
658 | 690 | The closure type is declared in the smallest block
|
659 | 691 | scope, class scope, or namespace scope that contains the corresponding
|
660 | 692 | \grammarterm{lambda-expression}. \enternote This determines the set of namespaces and
|
|
742 | 774 | applies to the corresponding function call operator or operator template.
|
743 | 775 | An \grammarterm{attribute-specifier-seq} in a \grammarterm{lambda-declarator} appertains
|
744 | 776 | to the type of the corresponding function call operator or operator template.
|
| 777 | +The function call operator or any given operator template specialization |
| 778 | +is a constexpr function if either |
| 779 | +the corresponding \grammarterm{lambda-expression}{'s} |
| 780 | +\grammarterm{parameter-declaration-clause} is followed by \tcode{constexpr}, or |
| 781 | +it satisfies the requirements for a constexpr function~(\ref{dcl.constexpr}). |
745 | 782 | \enternote Names referenced in
|
746 | 783 | the \grammarterm{lambda-declarator} are looked up in the context in which the
|
747 | 784 | \grammarterm{lambda-expression} appears. \exitnote
|
| 785 | +\enterexample |
| 786 | +\begin{codeblock} |
| 787 | +auto ID = [](auto a) { return a; }; |
| 788 | +static_assert(ID(3) == 3); // OK |
| 789 | + |
| 790 | +struct NonLiteral { |
| 791 | + NonLiteral(int n) : n(n) { } |
| 792 | + int n; |
| 793 | +}; |
| 794 | +static_assert(ID(NonLiteral{3}).n == 3); // ill-formed |
| 795 | +\end{codeblock} |
| 796 | +\exitexample |
748 | 797 |
|
749 | 798 | \pnum
|
750 | 799 | The closure type for a non-generic \grammarterm{lambda-expression} with no
|
|
755 | 804 | The conversion is to ``pointer to \tcode{noexcept} function''
|
756 | 805 | if the function call operator
|
757 | 806 | has a non-throwing exception specification.
|
758 |
| -The |
759 |
| -value returned by this conversion function shall be the address of a function that, when |
760 |
| -invoked, has the same effect as invoking the closure type's function call operator. |
| 807 | +The value returned by this conversion function |
| 808 | +is the address of a function \tcode{F} that, when invoked, |
| 809 | +has the same effect as invoking the closure type's function call operator. |
| 810 | +\tcode{F} is a constexpr function |
| 811 | +if the function call operator is a constexpr function. |
761 | 812 | For a generic lambda with no \grammarterm{lambda-capture}, the closure type has a
|
762 | 813 | conversion function template to
|
763 | 814 | pointer to function. The conversion function template has the same invented
|
|
766 | 817 | the pointer to function shall behave as if it were a
|
767 | 818 | \grammarterm{decltype-specifier} denoting the return type of the corresponding
|
768 | 819 | function call operator template specialization.
|
769 |
| -\enternote If the generic lambda has no \grammarterm{trailing-return-type} or |
| 820 | +\enternote |
| 821 | +If the generic lambda has no \grammarterm{trailing-return-type} or |
770 | 822 | the \grammarterm{trailing-return-type} contains a placeholder type, return type
|
771 | 823 | deduction of the corresponding function call operator template specialization
|
772 | 824 | has to be done. The corresponding specialization is that instantiation of the
|
|
794 | 846 | };
|
795 | 847 | \end{codeblock}
|
796 | 848 | \exitnote
|
| 849 | + |
797 | 850 | \enterexample
|
798 | 851 | \begin{codeblock}
|
799 | 852 | void f1(int (*)(int)) { }
|
|
813 | 866 | int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK
|
814 | 867 | \end{codeblock}
|
815 | 868 | \exitexample
|
| 869 | + |
816 | 870 | The value returned by any given specialization of this conversion function
|
817 |
| -template shall be the address of a function that, when invoked, has the same |
| 871 | +template is the address of a function \tcode{F} that, when invoked, has the same |
818 | 872 | effect as invoking the generic lambda's corresponding function call operator
|
819 | 873 | template specialization.
|
| 874 | +\tcode{F} is a constexpr function |
| 875 | +if the corresponding specialization is a constexpr function. |
820 | 876 | \enternote
|
821 | 877 | This will result in the implicit instantiation of the generic lambda's body.
|
822 | 878 | The instantiated generic lambda's return type and parameter types shall match
|
|
829 | 885 | GL_int(3); // OK: same as \tcode{GL(3)}
|
830 | 886 | \end{codeblock}
|
831 | 887 | \exitexample
|
| 888 | + |
832 | 889 | The conversion function or conversion function template is public,
|
833 |
| -non-virtual, non-explicit, const, and has a non-throwing exception |
| 890 | +constexpr, non-virtual, non-explicit, const, and has a non-throwing exception |
834 | 891 | specification~(\ref{except.spec}).
|
| 892 | +\enterexample |
| 893 | +\begin{codeblock} |
| 894 | +auto Fwd = [](int (*fp)(int), auto a) { return fp(a); }; |
| 895 | +auto C = [](auto a) { return a; }; |
| 896 | + |
| 897 | +static_assert(Fwd(C,3) == 3); // OK |
| 898 | + |
| 899 | +// No specialization of the function call operator template can be constexpr (due to the local static). |
| 900 | +auto NC = [](auto a) { static int s; return a; }; |
| 901 | +static_assert(Fwd(NC,3) == 3); // ill-formed |
| 902 | +\end{codeblock} |
| 903 | +\exitexample |
835 | 904 |
|
836 | 905 | \pnum
|
837 | 906 | The \grammarterm{lambda-expression}'s \grammarterm{compound-statement} yields the
|
|
1048 | 1117 | An entity is \defnx{captured by reference}{captured!by~reference} if it is implicitly or explicitly
|
1049 | 1118 | captured but not captured by copy. It is unspecified whether additional unnamed
|
1050 | 1119 | non-static data members are declared in the closure type for entities captured by
|
1051 |
| -reference. A member of an anonymous union shall not be captured by reference. |
| 1120 | +reference. |
| 1121 | +If declared, such non-static data members shall be of literal type. |
| 1122 | +\enterexample |
| 1123 | +\begin{codeblock} |
| 1124 | +// The inner closure type must be a literal type regardless of how reference captures are represented. |
| 1125 | +static_assert([](int n) { return [&n] { return ++n; }(); }(3) == 4); |
| 1126 | +\end{codeblock} |
| 1127 | +\exitexample |
| 1128 | +A member of an anonymous union shall not be captured by reference. |
1052 | 1129 |
|
1053 | 1130 | \pnum
|
1054 | 1131 | If a \grammarterm{lambda-expression} \tcode{m2} captures an entity and that entity is
|
|
4702 | 4779 | zero~(\ref{expr.mul}), or certain shift operations~(\ref{expr.shift})
|
4703 | 4780 | \exitnote;
|
4704 | 4781 |
|
4705 |
| -\item |
4706 |
| -a \grammarterm{lambda-expression}~(\ref{expr.prim.lambda}); |
4707 |
| - |
4708 | 4782 | \item
|
4709 | 4783 | an lvalue-to-rvalue conversion~(\ref{conv.lval}) unless
|
4710 | 4784 | it is applied to
|
|
4755 | 4829 | automatic storage duration defined outside that
|
4756 | 4830 | \grammarterm{lambda-expression}, where
|
4757 | 4831 | the reference would be an odr-use~(\ref{basic.def.odr}, \ref{expr.prim.lambda});
|
| 4832 | +\enterexample |
| 4833 | +\begin{codeblock} |
| 4834 | +void g() { |
| 4835 | + const int n = 0; |
| 4836 | + [=] { |
| 4837 | + constexpr int i = n; // OK, \tcode{n} is not odr-used and not captured here |
| 4838 | + constexpr int j = *&n; // ill-formed, \tcode{\&n} would be an odr-use of \tcode{n} |
| 4839 | + }; |
| 4840 | +} |
| 4841 | +\end{codeblock} |
| 4842 | +\exitexample |
| 4843 | +\enternote |
| 4844 | +If the odr-use occurs in an invocation |
| 4845 | +of a function call operator of a closure type, |
| 4846 | +it no longer refers to \tcode{this} or to an enclosing automatic variable |
| 4847 | +due to the transformation~(\ref{expr.prim.lambda}) |
| 4848 | +of the \grammarterm{id-expression} into |
| 4849 | +an access of the corresponding data member. |
| 4850 | +\enterexample |
| 4851 | +\begin{codeblock} |
| 4852 | +auto monad = [](auto v) { return [=] { return v; }; }; |
| 4853 | +auto bind = [](auto m) { |
| 4854 | + return [=](auto fvm) { return fvm(m()); }; |
| 4855 | +}; |
| 4856 | + |
| 4857 | +// OK to have captures to automatic objects created during constant expression evaluation. |
| 4858 | +static_assert(bind(monad(2))(monad)() == monad(2)()); |
| 4859 | +\end{codeblock} |
| 4860 | +\exitexample |
| 4861 | +\exitnote |
4758 | 4862 |
|
4759 | 4863 | \item
|
4760 | 4864 | a conversion from type \cv{} \tcode{void *} to a pointer-to-object type;
|
|
0 commit comments