C++: Declaration of template class member specialization (+ Doxygen bonus question!)
- by Ziv
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:
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).
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.
The most immediate consequence of this issue, as I mentioned, is my Doxygen documentation, which doesn't seem to warm to the idea of member specialization, at least the way I'm defining it at the moment. It will always present only the first definition it finds of a function/constant, and I really need to be able to present the specializations as well. If I go so far as to re-declare the entire class, i.e. in the header:
/* template declaration */
template<class T> class X {
public:
static T v;
static void f(T);
};
/* template member definition */
template<class T> T X<T>::v = 0;
template<class T> void X<T>::f(T arg) { v = arg; }
/* declaration of specialized CLASS (with definitions in .cpp) */
template<> class X<float> {
public:
static float v;
static void f(float);
};
then it will display the different variations of X as different classes (which is fine by me), but I don't know how to get the same effect when specializing only a few select members of the class. I don't know if this is a mistake of mine, or a limitation of Doxygen - any ideas?
Thanks much,
Ziv