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
Consider:
template<typename T> struct S {
S(const S&) = default;
S& operator=(const S&) = default;
int n;
};
// Are the explicit specializations OK?
template<> S<int>::S(const S&) noexcept { }
template<> S<int>& S<int>::operator=(const S& other) noexcept {
return *this;
}
If the explicit specialization were allowed, would the answer to std::is_trivially_copyable<S<int>> change? What is decltype(&S::operator=) (the defaulted definition is noexcept, yet no instantiation or implicit definition is triggered)?
Proposed resolution (2023-10-20) [SUPERSEDED]:
Change in 13.9.2 [temp.inst] paragraph 3 and add bullets as follows:
The implicit instantiation of a class template specialization causesThe implicit instantiation of a class template specialization does not cause the implicit instantiation of default arguments or noexcept-specifiers of the class member functions.
- the implicit instantiation of the declarations, but not of the definitions, of the
non-deleteduser-provided class member functions, member classes, scoped member enumerations, static data members, member templates, and friends; and- the implicit instantiation of the definitions of
[ Note: The implicit instantiation determines whether a defaulted function is deleted, but a non-deleted defaulted function is implicitly defined only when it is odr-used or needed for constant evaluation. -- end note ]
- defaulted and deleted member functions as defaulted (9.5.2 [dcl.fct.def.default]) or deleted (9.5.3 [dcl.fct.def.delete]),
- unscoped member enumerations, and
- member anonymous unions.
Additional notes (October, 2023)
It is desirable to require a diagnostic for such attempted explicit specializations.
Furthermore, there are situations where the "potentially-throwing" property of a non-deleted function is queried:
template<int...> struct C { // This class has no eligible copy assignment operator at all. void operator=(const C&) requires false; void operator=(int) noexcept; operator int() const; }; void f(C<> &c) { c = c; // Convert to int, then construct from int. } struct D { C<> c; }; bool g(D d) { return noexcept(d = d); // #1. If this is valid, what does it return? } struct E { C<> c; E &operator=(const E &o) { c = o.c; } };
All major implementations agree that E is valid. However, clang, gcc, and EDG delete the copy assignment operator of D, thus sidestepping the question at #1. (MSVC accepts, but #1 returns true despite the potentially-throwing conversion to int.) Apparently, user-defined conversions for the first argument of C's assignment operator are ignored in implementations other than MSVC. However, the specification is silent on that.
Possible resolution:
Change in 13.9.2 [temp.inst] paragraph 3 and add bullets as follows:
The implicit instantiation of a class template specialization causesThe implicit instantiation of a class template specialization does not cause the implicit instantiation of default arguments or noexcept-specifiers of the class member functions.
- the implicit instantiation of the declarations, but not of the definitions, of the
non-deleteduser-provided class member functions, member classes, scoped member enumerations, static data members, member templates, and friends; and- the implicit instantiation of the definitions of
[ Note: The implicit instantiation determines whether a defaulted function is deleted, but a non-deleted defaulted function is implicitly defined only when it is odr-used or needed for constant evaluation. -- end note ]
- defaulted and deleted member functions as defaulted (9.5.2 [dcl.fct.def.default]) or deleted (9.5.3 [dcl.fct.def.delete]),
- unscoped member enumerations, and
- member anonymous unions.
Change in 13.9.4 [temp.expl.spec] paragraph 7 as follows:
If a template, a member template or a member of a templated classtemplateis explicitly specialized, a declaration of that specialization shall be reachable from every use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required unless the specialization is for a member of a templated class whose definition is implicitly instantiated as a result of the implicit instantiation of the class (13.9.2 [temp.inst]). ...