简体   繁体   中英

A confusion about explicit specialization for member of class template

template<class T> struct A {
  struct B { };
  template<class U> struct C { 
      void show();
  };
};

template<>
template<>
void A<int>::C<int>::show(){  //#1

}

int main(){

}

Consider the above code , At #1 , it's an explicit specialization definition for member of member class template. Some rules will be applied to it as the following specified:

temp.expl.spec#5

A member of an explicitly specialized class is not implicitly instantiated from the member declaration of the class template; instead, the member of the class template specialization shall itself be explicitly defined if its definition is required. In this case, the definition of the class template explicit specialization shall be in scope at the point at which the member is defined . The definition of an explicitly specialized class is unrelated to the definition of a generated specialization. That is, its members need not have the same names, types, etc. as the members of a generated specialization. Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax. The same is true when defining a member of an explicitly specialized member class. However, template<> is used in defining a member of an explicitly specialized member class template that is specialized as a class template.

Firstly, what's explicitly specialized class ? Does it refer to the entity which has explicit specialization declaration? It seems to it doesn't mean it, please look at the example in Explicitly specialized class part

template<> template<> class A<int>::B<double>;

According to that example, A<int> within the explicit specialization for member can be called a explicitly specialized class . So, In my first example A<int> and C<int> are all explicitly specialized class ? I'm not sure. I feel the phrase explicitly specialized class is not clear in this section.

Please note the emphasized part, it means the enclosing class template explicit specialization shall appear in the same scope as that of explicit specialization definition for its member. The member is defined in global scope but there's no any explicit specialization definition for A<int> or C<int> that appears in the global scope. How to interpret this?

By the way, as a opposite example:

template<class T> struct A {
  struct B { };
  template<class U> struct C { 
      void show();
  };
};

template<>
template<typename U>
struct A<int>::C{  //#2
    void show();
};

template<>
template<typename U>
void A<int>::C<U>::show(){  //#3

}

int main(){

}

why such code is required an explicit specialization for class template C before #3 , what's the difference between such two examples?

Explicitly specialized class

The phrase "explicitly specialized class" is unclear in this section,

temp.expl.spec#15

A member or a member template may be nested within many enclosing class templates. In an explicit specialization for such a member, the member declaration shall be preceded by a template<> for each enclosing class template that is explicitly specialized .

[ Example:  
template<class T1> class A {
  template<class T2> class B {
    void mf();
  };
};
template<> template<> class A<int>::B<double>;
template<> template<> void A<char>::B<char>::mf();
— end example ]  

what's the explicitly specialized class mean, Is it refer to an entity that have a explicit specialization declaration or something others? It seems to no explicit specialization for A<int> in the above example.

There is no confusion there, you have to parse those statements (C++ and English) according to their grammatical structure. Source code is description of program in language understandable for humans. Programming language is a tool of human cooperation.

CWG529 removed need to understand intuitively by changing wording to explain order and content of template-ids.

Here you declared template of class A with template parameter T, which contains class B and a nested declaration of template class C with template parameter U, which contains a method show() :

template<class T> struct A {
  struct B { };
  template<class U> struct C { 
      void show();
  };
};

Here you declared, that for explicitly specialized template class A (which required to have it declared first) with T = int that there is a template class C which contains method show()

template<>
template<typename U>
struct A<int>::C{  //#2
    void show();
};

This declaration doesn't contradict previous one, but because it's a specialization of class A, it may expand it: You can do this:

template<>
template<typename U>
struct A<int>::C{  //#4
    void hide();
};

Which means that for any A with T=int , there is a template class C that got member hide() . But other A's will have template class C with member show() . What previous statement did that it removed any doubts about content of C for this A's specialization.

Now this only defines member function show() for all C's contained in A<int> :

template<>
template<typename U>
void A<int>::C<U>::show(){  //#3

}

You don't have an explicit specialization of C here, which is an enclosing class for show() . the memeber id show() is preceded by an unspecialized template-id template<typename U> ... C<U> . There is only a definition of member function but it requires a visible declaration of that template C - the #2 part. The visibility may be attained by various means and "the scope" mentioned is generalized description of it.

Omitting part #2 would be a semantic equivalent of writing:

class C;

void C::show() { // ill-formed - C is an incomplete type.
}

We would know that all of A's contain some class C, but we don't have a complete definition for that particular C in specialized A<int> (and it may be different).

This statement actually states that specialization C<int> nested in specialization A<int> contains show()

template<>
template<>
void A<int>::C<int>::show(){  //#1

}

Any possibility of contradiction, ambiguity or uncertainty (aside from undefined behavior) are leading to ill-formed code and rules are meant to form the framework of limitations against which the code should be checked. With absence of #2, the #3 at some point could be followed by #4, then the #3 statement would become illegal and thus it is deemed as such. #2 and #4 at same time would be two definitions of same thing which also leads either to ill-formed code if they are present in same unit, or they would lead to undefined behavior if they are present in separate units within program.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM