The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type, whose properties are described below.
The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. [ Note: This determines the set of namespaces and classes associated with the closure type ([basic.lookup.argdep]). The parameter types of a lambda-declarator do not affect these associated namespaces and classes. — end note ] The closure type is not an aggregate type ([dcl.init.aggr]). An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than by changing:
the size and/or alignment of the closure type,
whether the closure type is trivially copyable,
whether the closure type is a standard-layout class, or
whether the closure type is a POD class.
An implementation shall not add members of rvalue reference type to the closure type.
[ Example:
auto monoid = [](auto v) { return [=] { return v; }; }; auto add = [](auto m1) constexpr { auto ret = m1(); return [=](auto m2) mutable { auto m1val = m1(); auto plus = [=](auto m2val) mutable constexpr { return m1val += m2val; }; ret = plus(m2()); return monoid(ret); }; }; constexpr auto zero = monoid(0); constexpr auto one = monoid(1); static_assert(add(one)(zero)() == one()); auto two = monoid(2); assert(two() == 2); static_assert(add(one)(one)() == two()); static_assert(add(one)(one)() == monoid(2)());
— end example ]
The closure type for a non-generic lambda-expression with no lambda-capture has a conversion function to pointer to function with C++ language linkage having the same parameter and return types as the closure type's function call operator. The conversion is to “pointer to noexcept function” if the function call operator has a non-throwing exception specification. The value returned by this conversion function is the address of a function F that, when invoked, has the same effect as invoking the closure type's function call operator. F is a constexpr function if the function call operator is a constexpr function. For a generic lambda with no lambda-capture, the closure type has a conversion function template to pointer to function. The conversion function template has the same invented template-parameter-list, and the pointer to function has the same parameter types, as the function call operator template. The return type of the pointer to function shall behave as if it were a decltype-specifier denoting the return type of the corresponding function call operator template specialization.
[ Note: If the generic lambda has no trailing-return-type or the trailing-return-type contains a placeholder type, return type deduction of the corresponding function call operator template specialization has to be done. The corresponding specialization is that instantiation of the function call operator template with the same template arguments as those deduced for the conversion function template. Consider the following:
auto glambda = [](auto a) { return a; }; int (*fp)(int) = glambda;
The behavior of the conversion function of glambda above is like that of the following conversion function:
struct Closure { template<class T> auto operator()(T t) const { ... } template<class T> static auto lambda_call_operator_invoker(T a) { ... } template<class T> using fptr_t = decltype(lambda_call_operator_invoker(declval<T>())) (*)(T); template<class T> operator fptr_t<T>() const { return &lambda_call_operator_invoker; } };
— end note ]
[ Example:
void f1(int (*)(int)) { } void f2(char (*)(int)) { } void g(int (*)(int)) { } void g(char (*)(char)) { } void h(int (*)(int)) { } void h(char (*)(int)) { } auto glambda = [](auto a) { return a; }; f1(glambda); f2(glambda); g(glambda); h(glambda); int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; };
— end example ]
The value returned by any given specialization of this conversion function template is the address of a function F that, when invoked, has the same effect as invoking the generic lambda's corresponding function call operator template specialization. F is a constexpr function if the corresponding specialization is a constexpr function. [ Note: This will result in the implicit instantiation of the generic lambda's body. The instantiated generic lambda's return type and parameter types shall match the return type and parameter types of the pointer to function. — end note ] [ Example:
auto GL = [](auto a) { std::cout << a; return a; }; int (*GL_int)(int) = GL; GL_int(3);
— end example ]
The conversion function or conversion function template is public, constexpr, non-virtual, non-explicit, const, and has a non-throwing exception specification. [ Example:
auto Fwd = [](int (*fp)(int), auto a) { return fp(a); }; auto C = [](auto a) { return a; }; static_assert(Fwd(C,3) == 3); auto NC = [](auto a) { static int s; return a; }; static_assert(Fwd(NC,3) == 3);
— end example ]
The closure type associated with a lambda-expression has no default constructor and a deleted copy assignment operator. It has a defaulted copy constructor and a defaulted move constructor ([class.copy]). [ Note: These special member functions are implicitly defined as usual, and might therefore be defined as deleted. — end note ]
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4