cplusplus / CWG

Core Working Group
23 stars 7 forks source link

[temp.expl.spec] p7 The intent may not merely refer to implicit instantiation #399

Open xmh0511 opened 1 year ago

xmh0511 commented 1 year ago

Full name of submitter (unless configured in github; will be published with the issue): Jim X

The original issue is https://github.com/cplusplus/draft/issues/4816

[temp.expl.spec]

If a template, a member template or a member of a class template is 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.

Consider the formal example after the above rule

template<class T> struct A {
  enum E : T;
  enum class S : T;
};
template<> enum A<int>::E : int { eint };           // OK
template<> enum class A<int>::S : int { sint };     // OK
template<class T> enum A<T>::E : T { eT };
template<class T> enum class A<T>::S : T { sT }; 

template<> enum A<char>::E : char { echar };  // error: A<char>​::​E was instantiated
                                                                               // when A<char> was instantiated

template<> enum class A<char>::S : char { schar };  // OK

The comment in the last line says it's ok, however, doesn't A<char> cause the implicit instantiation of S? As per [temp.inst] p3

The implicit instantiation of a class template specialization causes

  • the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends; and
  • the implicit instantiation of the definitions of deleted member functions, unscoped member enumerations, and member anonymous unions.

Hence, presumably, the intent of [temp.expl.spec] p7 does not merely refer to an implicit instantiation. Consider this case

template<class T> struct A {
  enum E : T;
  enum class S : T;
};
template<> enum A<int>::E : int { eint };           // OK
template<> enum class A<int>::S : int { sint };     // OK
// template<class T> enum A<T>::E : T { eT };  comment this definition
template<class T> enum class A<T>::S : T { sT }; 

template<> enum A<char>::E : char { echar };   // OK

template<> enum class A<char>::S : char { schar };  // OK

If we comment the definition of A<T>::E, then the explicit specialization template<> enum A<char>::E : char { echar }; is also ok(both in GCC and Clang), however, [temp.inst] p3 still applies(i.e implicitly instantiates) here regardless of whether A<T>::E has its definition or not. So, Is the following rule the original intent of [temp.expl.spec] p7?

If a template, a member template or a member of a class template is explicitly specialized, a declaration of that specialization shall be reachable from every use of that specialization that would cause an implicit instantiation of the definition to take place and the entity whose specialization is being implicit instantiated has been defined at the point of instantiation, in every translation unit in which such a use occurs; no diagnostic is required.