Declaration of template class member specialization

Ziv picture Ziv · Mar 23, 2010 · Viewed 14.9k times · Source

When I specialize a (static) member function/constant in a template class, I'm confused as to where the declaration is meant to go.

Here's an example of what I what to do - yoinked directly from IBM's reference on template specialization:

===IBM Member Specialization Example===

template<class T> class X {
public:
   static T v;
   static void f(T);
};

template<class T> T X<T>::v = 0;
template<class T> void X<T>::f(T arg) { v = arg; }

template<> char* X<char*>::v = "Hello";
template<> void X<float>::f(float arg) { v = arg * 2; }

int main() {
   X<char*> a, b;
   X<float> c;
   c.f(10); // X<float>::v now set to 20
}

The question is, how do I divide this into header/cpp files? The generic implementation is obviously in the header, but what about the specialization?

It can't go in the header file, because it's concrete, leading to multiple definition. But if it goes into the .cpp file, is code which calls X::f() aware of the specialization, or might it rely on the generic X::f()?

So far I've got the specialization in the .cpp only, with no declaration in the header. I'm not having trouble compiling or even running my code (on gcc, don't remember the version at the moment), and it behaves as expected - recognizing the specialization. But A) I'm not sure this is correct, and I'd like to know what is, and B) my Doxygen documentation comes out wonky and very misleading (more on that in a moment a later question).

What seems most natural to me would be something like this, declaring the specialization in the header and defining it in the .cpp:

===XClass.hpp===

#ifndef XCLASS_HPP
#define XCLASS_HPP

template<class T> class X {
public:
   static T v;
   static void f(T);
};

template<class T> T X<T>::v = 0;
template<class T> void X<T>::f(T arg) { v = arg; }

/* declaration of specialized functions */
template<> char* X<char*>::v;
template<> void X<float>::f(float arg);

#endif

===XClass.cpp===

#include <XClass.hpp>

/* concrete implementation of specialized functions */
template<> char* X<char*>::v = "Hello";
template<> void X<float>::f(float arg) { v = arg * 2; }

...but I have no idea if this is correct. Any ideas?

Answer

Georg Fritzsche picture Georg Fritzsche · Mar 23, 2010

Usually you'd just define the specializations inline in the header as dirkgently said.

You can define specializations in seperate translation units though if you are worried about compilation times or code bloat:

// x.h:
template<class T> struct X {
    void f() {}
}

// declare specialization X<int>::f() to exist somewhere: 
template<> void X<int>::f();

// translation unit with definition for X<int>::f():
#include "x.h"
template<> void X<int>::f() {
    // ...
}

So yes, your approach looks fine. Note that you can only do this with full specializations, thus it is often impractical to do this.

For details, see e.g. Comeaus template FAQ.