Created on 2013-01-19.00:00:00 last changed 121 months ago
[Moved to DR at the February, 2014 meeting.]
Proposed resolution (September, 2013):
Change 7.5.6 [expr.prim.lambda] paragraph 2 as follows:
...A lambda-expression shall not appear in an unevaluated operand (Clause 7 [expr]), in a template-argument, in an alias-declaration, in a typedef declaration, or in the declaration of a function or function template outside its function body and default arguments. [Note: The intention is to prevent lambdas from appearing in a signature —end note]. [Note: A closure object behaves like a function object (22.10 [function.objects]). —end note]
Additional notes, April, 2013:
Further discussion has arisen regarding lambda-expressions in function template signatures. Although the restriction that lambda-expressions cannot appear as unevaluated operands (7.5.6 [expr.prim.lambda] paragraph 2) was intended to avert the need to deal with them in function template signatures, the fact that 7.7 [expr.const] treats unevaluated subexpressions separately from unevaluated operands opens another avenue for lambda-expressions in template signatures, e.g.,
template<typename T> void f(int [(0 && [] { for (auto x : T()) {} }, 1)]);
Four possible approaches for dealing with this issue have been suggested:
Allow lambda-expressions in function template signatures. This would be costly in some implementations.
Give a function template internal linkage if its signature includes a lambda-expression. This would allow SFINAE and redeclaration to work without requiring that lambda-expressions be mangled.
Specify that a function signature containing a lambda-expression is not a redeclaration of any other function template, which would allow SFINAE to work but not require declaration matching and mangling.
Do not allow lambda-expressions in function template signatures.
If any of these approaches were adopted, the rationale for disallowing lambda-expressions in unevaluated operands would be removed, so it might make sense to remove the restriction at the same time.
Lambda expressions cannot appear in unevaluated operands nor in evaluated portions of constant expressions. However, the following example appears to circumvent those restrictions:
template <bool> struct BoolSink { typedef void type; }; template <typename T, typename U> struct AddRvalueReferenceImpl { typedef T type; }; template <typename T> struct AddRvalueReferenceImpl<T, typename BoolSink<false && [] { extern T &&tref; }>::type> { typedef T &&type; }; template <typename T> struct AddRvalueReference : AddRvalueReferenceImpl<T, void> { }; namespace ImplHelpers { template <typename T> typename AddRvalueReference<T>::type create(void) { } } template <typename T, typename U, typename ...Args> struct IsConstructibleImpl { enum { value = 0 }; }; template <typename T, typename ...Args> struct IsConstructibleImpl<T, typename BoolSink<false && [] { T t( ::ImplHelpers::create<Args>() ...); }>::type, Args ...> { enum { value = 1 }; }; template <typename T, typename ...Args> struct IsConstructible : IsConstructibleImpl<T, void, Args ...> { }; struct DestroyMe { ~DestroyMe() = delete; }; static_assert(+IsConstructible<int>::value, "error"); static_assert(!IsConstructible<void>::value, "error"); static_assert(+IsConstructible<int [1]>::value, "error"); static_assert(!IsConstructible<DestroyMe>::value, "error"); static_assert(!IsConstructible<int *, char *>::value, "error"); static_assert(+IsConstructible<int &&, int>::value, "error"); static_assert(!IsConstructible<int &&, int &>::value, "error"); static_assert(+IsConstructible<int &&, int &&>::value, "error");
Is this intended?
History | |||
---|---|---|---|
Date | User | Action | Args |
2014-11-24 00:00:00 | admin | set | status: dr -> c++14 |
2014-03-03 00:00:00 | admin | set | messages: + msg4935 |
2014-03-03 00:00:00 | admin | set | status: ready -> dr |
2013-10-14 00:00:00 | admin | set | messages: + msg4572 |
2013-10-14 00:00:00 | admin | set | status: drafting -> ready |
2013-05-03 00:00:00 | admin | set | messages: + msg4329 |
2013-05-03 00:00:00 | admin | set | status: open -> drafting |
2013-01-19 00:00:00 | admin | create |