mercredi 25 juillet 2018

Can we declare a partial specialization of a template class member after instantiation of the enclosing class template?

Let's consider this simple exemple:

template<class T>
struct A{
  template<class V,class=void>
  struct B{
    static const int value=1 ;
  };
};

#ifdef PRE_INSTANTIATION
A<int> a;
#endif

#ifdef PARTIAL_SPECIALIZATION_OF_TEMPLATE_MEMBER
template<class T>
template<class V>
struct A<T>::B<double,V>{
  static const int value = 2;
};
#else //PARTIAL_SPECIALIZATION_OF_SPECIALIZATION_MEMBER
template<>
template<class V>
struct A<int>::B<double,V>{
  static const int value = 2;
};
#endif

static_assert(A<int>::B<int>::value==1,"");
#if __clang__ && PRE_INSTANTIATION && PARTIAL_SPECIALIZATION_OF_TEMPLATE_MEMBER
  //Unexpected =>
  static_assert(A<int>::B<double>::value==1,"");
#else //Expected =>
  static_assert(A<int>::B<double>::value==2,"");
#endif

clang does not consider the partial specialization of template B. GCC always considers it. clang has this "unexpected" behavior only if we force A<int> instantiation before we declare the partial specialization of A<T>::B. clang has the expected behavior if we declare a partial specialization of the specialized primary template A<int>::B.

Is clang right? Or is there any undiagnosticed UB here?


Notice all clang version since c++11 support have this behavior and all gcc version since c++11 support have the "expected" behavior. Code here

Aucun commentaire:

Enregistrer un commentaire