##### cppreference.com

##### Search

Create account

##### Namespaces

- Page
- Discussion

##### Variants

##### Views

- View
- Edit
- History

##### Actions

# partial template specialization

From cppreference.com
< cpp‎ | language

Allows customizing class templates for a given category of template arguments.

### [edit] Syntax

`template` `<` parameter-list `>` class-key class-head-name `<` argument-list `>` declaration |  |

where class-head-name identifies the name of a previously declared class template.

For example,

    template<class T1, class T2, int I>
    class A {}; // primary template

    template<class T, int I>
    class A<T, T*, I> {}; // partial specialization where T2 is a pointer to T1

    template<class T, class T2, int I>
    class A<T*, T2, I> {}; // partial specialization where T1 is a pointer

    template<class T>
    class A<int, T*, 5> {}; // partial specialization where T1 is int, I is 5,
                            // and T2 is a pointer

    template<class X, class T, int I>
    class A<X, T*, I> {}; // partial specialization where T2 is a pointer

Examples of partial specializations in the standard library include std::unique_ptr, which has a partial specialization for array types.

### [edit] The argument list

The following restrictions apply to the argument-list of a partial template specialization:

1) The argument list cannot be identical to the non-specialized argument list (it must specialize something)

    template<class T1, class T2, int I> class A {}; // primary template
    template<class X, class Y, int N> class A<X,Y,N> {}; // error

2) Default arguments cannot appear in the argument list
3) The specialization has to be more specialized than the primary template
4) If any argument is a pack expansion, it must be the last argument in the list
5) Non-type argument expression cannot use the name of the template parameter except when it is exactly the name of the template parameter

    template <int I, int J> struct A {}; // primary template
    template <int I> struct A<I+5, I*2> {}; // error
    template <int I> struct A<I, I> {}; // OK

6) Non-type template argument cannot specialize a template parameter whose type depends on a parameter of the specialization:

    template <class T, T t> struct C {}; // primary template
    template <class T> struct C<T, 1>; // error: type of the argument 1 is T,
                                       // which depends on the parameter T

    template< int X, int (*array_ptr)[X] > class A {}; // primary template
    int array[5];
    template< int X > class A<X,&array> { }; // error: type of the argument &array
                                 // is int(*)[X], which depends on the parameter X

### [edit] Name lookup

Partial template specializations are not found by name lookup. Only if the primary template is found by name lookup, its partial specializations are considered. In particular, a using declaration that makes a primary template visible, makes partial specializations visible as well:

    namespace N {
        template<class T1, class T2> class A { }; // primary template
    }
    using N::A; // refers to the primary template
    namespace N {
        template<class T> class A<T, T*> { }; // partial specialization
    }
    A<int,int*> a; // name lookup finds N::A (the primary template),
                   // the partial specialization with T = int is then used

### [edit] Matching

When a class template is instantiated, and there are partial specializations avaiable, the compiler has to decide if the primary template is going to be used or one of its partial specializations.

1) If only one specialization matches the template arguments, that specialization is used
2) If more than one specialization matches, partial order rules are used to determine which specialization is more specialized. The most specialized specialization is used, if it is unique (if it is not unique, the program cannot be compiled)
a)
3) If no specializations match, the primary template is used

    // given the template A as defined above
    A<int, int, 1> a1; // no specializations match, uses primary template
    A<int, int*, 1> a2; // uses partial specialization #1 (T=int, I=1)
    A<int, char*, 5> a3; // uses partial specialization #3, (T=char)
    A<int, char*, 1> a4; // uses partial specialization #4, (X=int, T=char, I=1)
    A<int*, int*, 2> a5; // error: matches #2 (T=int, T2=int*, I=2)
                         //        matches #4 (X=int*, T=int, I=2)
                         // neither one is more specialized than the other

| This section is incomplete Reason: partial order in more detail

### [edit] Members of partial specializations

The template parameter list and the template argument list of a member of a partial specialization must match the parameter list and the argument list of the partial specialization.

Just like with members of primary templates, they only need to be defined if used in the program.

Members of partial specializations are not related to the members of the primary template.

Explicit (full) specialization of a member of a partial specialization is declared the same way as an explicit specialization of the primary template.

    template<class T, int I>  // primary template
    struct A {
        void f(); // member declaration
    };

    template<class T, int I>
    void A<T,I>::f() { } // primary template member definition

    // partial specialization
    template<class T>
    struct A<T,2> {
        void f();
        void g();
        void h();
    };

    // member of partial specialization
    template<class T>
    void A<T,2>::g() { }

    // explicit (full) specialization
    // of a member of partial specialization
    template<>
    void A<char,2>::h() {}

    int main() {
        A<char,0> a0;
        A<char,2> a2;
        a0.f(); // OK, uses primary template’s member definition
        a2.g(); // OK, uses partial specialization's member definition
        a2.h(); // OK, uses fully-specialized definition of
                // the member of a partial specialization
        a2.f(); // error: no definition of f() in the partial
                // specialization A<T,2> (the primary template is not used)
    }

If a class template is a member of another class template, and it has partial specializations, these specializations are members of the enclosing class template. If the enclosing template is instantiated, the declarations of each member partial specialization is instantiated as well (the same way declarations, but not definitions, of all other members of a template are instantiated)

If the primary member template is explicitly (fully) specialized for a given (implicit) specialization of the enclosing class template, the partial specializations of the member template are ignored for this specialization of the enclosing class template.

If a partial specialization of the member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the primary member template and its other partial specializations are still considered for this specialization of the enclosing class template.

    template<class T> struct A { // enclosing class template
      template<class T2>
      struct B {}; // primary member template
      template<class T2>
      struct B<T2*> {}; // partial specialization of member template
    };

    template<>
    template<class T2>
    struct A<short>::B {}; // full specialization of primary member template
                           // (will ignore the partial)

    A<char>::B<int*> abcip; // uses partial specialization T2=int
    A<short>::B<int*> absip; // uses full specialization of the primary (ignores partial)
    A<char>::B<int> abci; // uses primary

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/language/partial_specialization&oldid=63617"
Category:

- Todo with reason