This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
Subclause 7.5.6.2 [expr.prim.lambda.closure] paragraph 2 specifies:
The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression.
This means the closure type is a local class if the lambda-expression appears at function scope. A note in 13.9.2 [temp.inst] paragraph 2 claims that default arguments inside local classes are not separately instantiated:
[Note 3: Within a template declaration, a local class (11.6 [class.local]) or enumeration and the members of a local class are never considered to be entities that can be separately instantiated (this includes their default arguments, noexcept-specifier s, and non-static data member initializers, if any, but not their type-constraints or requires-clauses). As a result, the dependent names are looked up, the semantic constraints are checked, and any templates used are instantiated as part of the instantiation of the entity within which the local class or enumeration is declared. —end note]
However, 13.9.2 [temp.inst] paragraph 3 is not in harmony with the note:
The implicit instantiation of a class template specialization does not cause the implicit instantiation of default arguments or noexcept-specifier s of the class member functions.
Example:
template<typename T>
void ft() {
[](T p = T::value) {}; // error even though the lambda is never called
}
template void ft<int>();
Even for a lambda declared at namespace scope is an unused default argument instantiated by major implementations:
template<typename T>
using ta = decltype([](T p = T::value) { // error
return p;
});
auto g = ta<int>{}(0);
CWG 2023-11-11
The behavior is as intended. Note that 13.9.2 [temp.inst] paragraph 3 applies to a class template specialization and its member functions. The examples do not involve class templates, but merely templated classes.