Daily Archives: 06 - Aug - 2004

Very brief intro to C++ template specializations

I was looking through my C++ templates book today, when I realized that a lot of these things were real obscure, so there’s a lot of programmers who wouldn’t know about them unless I could help explain it.

So what I’m going to be discussing is template specialization. Hopefully if you program in C++, you’re familiar with templates. They are a generic programming facility for C++, that can be applied to classes and functions. One of the more notable differences from normal classes is that templates must be defined in the header file where they’re declared.

class Foo {
   Foo(const T& thingy) : m_thingy(thingy) { }

   T m_thingy;
}; // class template

T max(const T &a, const T &b)
   return (a > b) ? a : b;
} // function template

Well, it turns out that you’re able to special-case code for a given type. For example, if you know you can do a better job implementing max(), as long as it’s working with an int, you can specialize max for that type, as follows:

int max(const int &a, const int &b)
   // Do your best pardner

You can also specialize templated classes. There’s two ways you can do so:

  1. Full specialization
  2. Member specialization

Before I explain it, let me give you an example class I’ll be using:

class Outer {
    void print(const T &value) const {

In full specialization, you redeclare the template class definition, but leave the space in between the template brackets blank, and add a bracketed definition to the end of your class name. You then replace all of the type names in your class definition with whatever type you're specializing for. You must do this for every method in the class.

// Specializing for bool, you must specialize all members!
class Outer {
    void print(const bool &value) const;
    void name() const; // We *have to* declare this too.

When defining the methods in this fashion, you don't precede the function with template , because your fully specialized class is no longer a template. Since your class is no longer a template, you can declare it in a header, and define it later in a .cpp, just like for normal classes.

// Don't precede with template, as this function isn't part of a template.
void Outer::print(const bool &value) const
    cout ::name() const

Now in member specialization, you don't bother re-defining the class. You just define the methods. This time you do have to precede with template .

// Full member specialization.  After this declarations, you can no longer
// provide a full specialization for Outer.  Notice we don't declare
// a class here, just some functions.  Notice also that we DO precede with
// template this time.
void Outer::print(const int &value) const

Note that both of these methods fail if you've already managed to have the generic form instantiated for that type, by declaring a variable using it. If you preceded Outer::print() with a Outer outVar; declaration, you'll have problems.

Also, note that when doing member specialization, you can usually just declare a non-template function with the same member name and arguments. In C++, a non-template function with the same signature as a template function will win in overload resolution.

Now if you go ahead and make a sample program using these classes (don't forget to include and your using namespace std; commands), you can see how it works.

// Notice that we didn't declare the name method again.  Instead, the generic
// version will be used.
int main(void)
    Outer f;
    Outer b;
    Outer i;




    return 0;

Building and running this program gives me the following output:

Hello from generic-ville!
Generic Outer class.
bool value is equal to 0
bool-specialized Outer class.
int value is equal to 2
Generic Outer class.

BTW, The book I was reading is C++ Templates: The Complete Guide by Vandevoorde and Josuttis. It's really a handy reference to have around for when templates are kicking your ass. =D