This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 119e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2026-04-17
(From submission #830.)
Consider:
struct Wrapper {
Wrapper(int) {}
};
template <int N>
struct Test {
Test() : w(0) {}
Wrapper w{}; //MSVC, GCC, EDG accept, but Clang rejects
};
Test<0> t;
Is the default member initializer instantiated together with the rest of the class template specialization, or only when actually needed?
Also consider:
template <int N>
struct Wrapper2 {
Wrapper2(int) {}
};
template <int N>
struct Test2 {
Test2() : w(0) {}
Wrapper2<N> w{}; //everybody accepts
};
Test2<0> t;
Possible resolution:
Change in 13.9.2 [temp.inst] paragraph 11 as follows:
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class or static data member of a templated class, or a substatement of a constexpr if statement (8.5.2 [stmt.if]), unless such instantiation is required.
[Note 4: The instantiation of a generic lambda does not require instantiation of substatements of a constexpr if statement within its compound-statement unless the call operator template is instantiated. —end note]
It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated.The use of a template specialization in a default argument or default member initializer shall not cause the template to be implicitly instantiated except where needed to determine the correctness of the default argument or default member initializer. The use of a default argument in a function call causes specializations in the default argument to be implicitly instantiated. Similarly, the use of a default member initializer in a constructor definition or an aggregate initialization causes specializations in the default member initializer to be instantiated.Let I be a default argument or default member initializer for a parameter or member, respectively, of type T, considering I to include the initialization of the parameter or member from the initializer-clause or brace-or-equal-initializer, respectively. Each templated entity X referenced by I is instantiated if needed to determine the correctness of I. Additionally, for the purposes of determining whether a definition of X is required to exist or whether the existence of a definition for X affects the semantics of the program, I is considered to be a templated function F having the form T F() { return I; }, and a function call, constructor definition or aggregate initialization that uses I is considered to call F. [Note: Whether X is instantiated can therefore depend on whether the definition of F is instantiated, which in turn can depend on whether a function call or aggregate initialization that uses I is potentially-evaluated. This rule applies even if I is not itself templated.]
CWG 2026-04-17
CWG agreed with the intent to make the Wrapper2 case well-formed. The end result should be consistent with unused default member initializers (not) causing odr-use.