ISO/ IEC JTC1/SC22/WG21 N0743

                                                 Document Number: WG21/N0743
                                                 Date: 8 July 1995
                                                 Project: Programming Language C++
                                                 Reply to: Sean A. Corfield
                                        Declaring specialisations - template issue 4.10
        N0701 = 95-0101 Template Issues and Proposed Resolutions, revision 12, item
        4.10 proposes a resolution to how to declare and define specialisations.
        Although this resolution had the support of the WG, an alternative was
        discussed that also had the support of the WG and was felt by some to be
        more consistent with other aspects of templates. The basic idea is that a
        specialisation and a primary template are opposite ends of a scale which
        has partial specialisations in between. It would therefore be more consistent
        if specialisations were syntactic more like both primary templates and
        partial specialisations.
        This paper proposes that the syntactic notation
        be used to introduce the declaration or definition of a specialisation.
        Consider the following template declaration:
                template<class T, class U, class V> void f(T*, U&, V);
        The following are successively more constrained partial specialisations:
                template<class U, class V> void f(int*, U&, V);
                template<class V> void f(int*, double&, V);
        What is the next logical 'partial' specialisation? At present, the next
        step is a (full) specialisation whose syntax looks like:
                void f<>(int*, double&, char);
        This does not have much similarity to the above three declarations. On the
        other hand, consider:
                template<> void f(int*, double&, char);
        This 'looks like' a partial specialisation with an empty list of parameters
        yet to be specialised - a full specialisation, in other words.
        When member templates are considered, this extra syntactic sugar can be more
                template<class X> struct A {
                        template<class Y> struct B;
                template<class X> template<class Y> struct A<X>::B { };
        Here, the two uses of 'template<...>' clearly indicate that a member
        template is present, but consider:
                template<class Z> struct A<int>::B { };
        Is it immediately obvious what this is? A template? A (partial)
        specialisation? Now consider this form:
                template<> template<class Z> struct A<int>::B { };
        Again, the two uses of 'template<...>' indicate a member template is
        being declared. The first 'template<>' indicates that the enclosing
        template is being specialised; the second, inner, 'template<...>' indicates
        that the member template is still not fully specialised.
        In my opinion, the primary benefit of the proposed notation is that it is
        similar to partial specialisation and, indeed, the original template
        declaration, showing more clearly that the specialisation does indeed relate
        to a template. Furthermore, the <> that was previously embedded in some
        specialisation declarations would no longer be necessary -- it was hard to
        spot before anyway.
        I also believe that given this change, most of the text of [temp.spec]
        could actually be folded into either the foregoing description of template
        declarations or the ensuing description of partial specialisations although
        I have not attempted to do this in the proposed WP changes.
        Require specialisations to be declared with the 'template<>' syntax.
WP changes
        [Most of the changes in the following are simply the insertion of
        'template<>' in the appropriate places -- I have not yet checked the
        WP for other places where specialisations appear that would also need to
        be changed to use the new notation]
        Replace 14.5 [temp.spec] with:
  14.5  Template specialization                              [temp.spec]
1 Except for a type member or template class member of a non-specialized
  template class, the following can be declared by a  declaration  where
  the declared name is a template-id: a specialized template function, a
  template class, or a static member of a template; that is:
                  template<> declaration
  [Note: a static member of a template can only be specialized in a defP
  inition due to syntactic restrictions.  ] [Example:
          template<class T> class stream;
          template<> class stream<char> { /* ... */ };
          template<class T> void sort(Array<T>& v) { /* ... */ }
          template<> void sort<char*>(Array<char*>&) ;
  Given  these declarations, stream<char> will be used as the definition
  of streams of chars; other streams will be handled by template classes
  generated  from  the  class  template.  Similarly, sort<char*> will be
  used as the sort function for arguments of  type  Array<char*>;  other
  Array  types  will be sorted by functions generated from the template.
2 A declaration of the template being specialized shall be in  scope  at
  the point of declaration of a specialization.  [Example:
          template<> class X<int> { /* ... */ }; // error: X not a template
          template<class T> class X { /* ... */ };
          template<> class X<char*> { /* ... */ }; // fine: X is a template
   --end example]
3 If a template is explicitly specialized then that specialization shall
  be declared before the first  use  of  that  specialization  in  every
  translation unit in which it is used.  [Example:
          template<class T> void sort(Array<T>& v) { /* ... */ }
          void f(Array<String>& v)
                  sort(v); // use general template
                           // sort(Array<T>&), T is String
          template<> void sort<String>(Array<String>& v); // error: specialize
                                                          // after use
          template<> void sort<>(Array<char*>& v); // fine sort<char*> not yet
                                                   // used
    --end  example]  If a function or class template has been explicitly
  specialized for a template-argument list  no  specialization  will  be
  implicitly generated for that template-argument list.
4 It is possible for a specialization with a given function signature to
  be generated by more than  one  function  template.   In  such  cases,
  explicit  specification  of  the  template  arguments  must be used to
  uniquely identify the template function instance that  is  being  speP
  cialized.  [Example:
          template <class T> void f(T);
          template <class T> void f(T*);
          template<> void f(int*);        // Ambiguous
          template<> void f<int>(int*);   // OK
          template<> void f(int);         // OK
   --end example]
5 Note  that a function with the same name as a template and a type that
  exactly  matches  that  of  a  template  is   not   a   specialization