Topic: Q: Specializing member templates of template classes


Author: tveldhui@seurat.uwaterloo.ca (Todd Veldhuizen)
Date: 1997/04/28
Raw View
I have a question about specializing member templates of template
classes.  I can't decide whether the standard permits specialization
of member templates of (nonspecialized) class templates without an
implicit instantiation of the class template.  Confused?  I am.

Example:

template<class T>
struct A {
    template<class X> void g(X);
};

// specialization of g for g(T) -- legal?
template<class T> template<>
void A<T>::g(T);


Here's an example which illustrates a use for such specializations:

template<class T>
class Vector {
public:
    template<class T2>
    Vector<T>& operator=(const Vector<T2>&);
};

// Default implementation
template<class T> template<class T2>
Vector<T>& operator=(const Vector<T2>&)
{
    // Assigning a vector of a different type; need to do conversion
    // T2 -> T for each element.
}

// Specialization
template<class T> template<>
Vector<T>& operator=(const Vector<T>&)
{
    // Assigning a vector of the same type; no conversion required,
    // so generate a call memcpy (faster)
}

The Jan'96 draft explicitly disallowed such specializations; sec. 14.5.1
said, "A specialized template function, a template class, or a static
member of a template can be declared by a declaration introduced by template<>
*except* for a type member or template class member of a non-specialized
template class."

This statement doesn't seem to be present in CD2; here are the
relevant clauses I could find:

> [14.7.3] [temp.expl.spec]
> An explicit specialization of any of the following:  [..]
> -- member function template of a class template
> [..] can be declared by a declaration introduced by template<>

The "introduced by template<>" doesn't seem to include declarations
such as "template<class T> template<>".  Later on in the same
section,

> 12 Member  function  templates,  member  class  templates of non-template
>   classes and class template specializations may be specialized  in  the
>   same manner as function templates and class templates.
> 13 A  specialization  of  a member function template or member class tem-
>   plate of a non-specialized class template is itself a template.

It's not clear whether item 13 should be read as "A specialization
of a (member function template/member class template) of a non-specialized
class template is itself a template." OR as "A specialization of
a member function template or (member class template of a non-specialized
class template) is itself a template."  The first interpretation seems
to imply that what I want to do is legal, while the second interpretation
doesn't.  Could this be clarified?

Item 15 in the same section gives examples of specializing member
templates of class templates, but they all require implicit instantiation
of the class template:

> 15 A member  template  of a class template may be explicitly specialized
>   for a given implicit instantiation of the class template, even if  the
>   member  template  is  defined  in  the  class template definition.  An
>   explicit specialization of a member template is  specified  using  the
>   template  specialization syntax.  Default function arguments shall not
>   be supplied in such declarations.  [Example:
>           template<class T> struct A {
>                   void f(T);
>                   template<class X> void g(T,X);
>                   void h(T) { }
>           };
>
>           // specialization
>           template<> void A<int>::f(int);
>
>           // out of class member template definition
>           template<class T> template<class X> void A<T>::g(T,X) { }
>           // member template partial specialization
>           template<> template<class X> void A<int>::g(int,X);
>
>           // member template specialization
>           template<> template<>
>                   void A<int>::g(int,char);        // X deduced as char
>           template<> template<>
>                   void A<int>::g<char>(int,char);  // X specified as char
>
>           // member specialization even if defined in class definition
>           template<> void A<int>::h(int) { }
>    --end example]

So in summary,

1.  Is it legal to do specializations of the sort I described above?
2.  If not, what is the rationale for disallowing such specializations?
3.  Have I missed something in the standard about this issue?  If not,
    can the language of the standard be revised to make this issue
    clearer?
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]