Alex Rivera | Logout

Understanding (simple?) C++ Partial Template Specialization

Asked 2011-05-26T12:27:01.907
23

Note: this seems to be a repost of a problem: C++ - Overload templated class method with a partial specilization of that method

I have boiled down a problem I am having with C++ template specialization down to a simple case.

It consists of a simple 2-parameter template class Thing, where I would like to specialize Thing<A,B>::doSomething() for B=int.

#include <cstdio>

// A 3-parameter template class.
template <class A, class B>
class Thing
{
public:
    Thing(A a, B b) : a_(a), b_(b) {}
    B doSomething();
private:
    A a_;
    B b_;
};

// The generic case works as expected.
template <class A, class B>
B Thing<A,B>::doSomething()
{
    return b_;
}

// This specialization does not work!
template <class A>
int Thing<A,int>::doSomething()
{
    return b_+1;
}

int main() {
    // Setup our thing.
    Thing<double,int> thing(1.0,2);
    // This doesn't compile - but works with the generic case.
    printf("Expecting 3, and getting %i\n", thing.doSomething());
    // Clean up.
    return 0;
}

Unfortunately, g++ exits with the error:

partial_specialization.cpp:30: error: invalid use of incomplete type ‘class Thing<A, int>’
partial_specialization.cpp:8: error: declaration of ‘class Thing<A, int>’

The clang++ compiler is a bit more verbose, but has the same problem:

partial_specialization.cpp:30:19: error: nested name specifier 'Thing<A, int>::' for declaration does not
      refer into a class, class template or class template partial specialization
int Thing<A,int>::doSomething()
    ~~~~~~~~~~~~~~^
partial_specialization.cpp:32:12: error: use of undeclared identifi
Edit
Report

1 Answer

61

Partial specialization of a function template, whether it is member function template or stand-alone function template, is not allowed by the Standard:

template<typename T, typename U> void f() {} //okay  - primary template
template<typename T> void f<T,int>() {}      //error - partial specialization
template<> void f<unsigned char,int>() {}    //okay  - full specialization

But you can partially specialize the class template itself. You can do something like this:

template <class A>
class Thing<A,int>  //partial specialization of the class template
{
    //..
    int doSomething();
};

template <class A>
int Thing<A,int>::doSomething()  { /* do whatever you want to do here */ }

Note that when you partially specialize a class template, then the template parameter-list of member function (in its definition outside the class), must match the template parameter list of the class template partial specialization. That means, for the above partial specialization of the class template, you cannot define this:

template <class A>
int Thing<A,double>::doSomething(); //error

Its not allowed, because the template parameter-list in function definition didn't match the template parameter-list of the class template partial specialization. §14.5.4.3/1 from the Standard (2003) says,

The template parameter list of a member of a class template partial specialization shall match the template parameter list of the class template partial specialization.[...]

For more on this, read my answer here:

C++ - Overload templated class method with a partial specilization of that method

answered 2011-05-26T12:29:55.737

Your Answer