PDA

View Full Version : Template specialization of a method


Fenris
2005.07.10, 10:49 AM
I have a templatized base class, and I want to specialize one of its methods (to control its return type). That means I define the class, let's say, as template <typename T> A. Now, all of its member functions need to be:

template <typename T> A<T>::MyFunc

Surely that can't be necessary? Isn't there a better way to specialize just one of the methods? Do I need to typedef it in some way?

OneSadCookie
2005.07.10, 06:32 PM
eg.

template <class T>
class X
{
public:
T foo(int x)
{
return T(x);
}
};

Fenris
2005.07.11, 04:22 AM
Aaah, thanks.

Fenris
2005.07.11, 09:17 AM
Right, I'm going to have to ask for some more help and insight here...

What I'm trying to achieve is a base class for a singleton, so that all my singleton classes can be derived off of it. So, I set about to create it, and it worked fairly well, apart from one little caveat:

static class bmSingleton* Instance (void) {return _instance;}

When I subclass a singleton from that, for instance BaseManager, I can't go:

myManager::Instance()->subclassedManagerData

because the return type of the instance is bmSingleton, not BaseManager, and subclassedManagerData isn't in bmSingleton. So, I have to cast the result of the Instance call to whatever type I expect it to be. Very cumbersome. Then, as if that wasn't enough, the static member in bmSingleton is static for bmSingleton which means that there isn't a static instance pointer for each singleton type, but only a single static instance pointer for all singletons, which is completely useless.

So, what I wanted to do was then to templatize this bmSingleton class so that I can pass in the type of the subclass and get the correct return type of the Instance() method, and a static instance pointer for each singleton type.

My header:

template <class T>
class bmSingleton
{
protected:
static T* instance;
public:
bmSingleton (void);
~bmSingleton ();

static T* Instance (void)
{
return instance;
}
};
template <class T> T* bmSingleton::instance = NULL;


Question #1: Is this even feasible? Will I actually get a separate instance pointer for each template class? Or will they still share some kind of confused instance pointer?
Question #2: The final line gives me a 'syntax error before ::' - any guesses as to why?
Question #3: Is it at all possible to send the bmSingleton, as a template type parameter, a subclass of itself? Can it contain a pointer to a subclass of itself?

All insight is very appreciated.

OneSadCookie
2005.07.11, 06:45 PM
singleton.hpp#ifndef singleton_hpp
#define singleton_hpp

template<class T>
class Singleton
{
public:
static T* instance()
{
return &_instance;
}

protected:
Singleton() {}

private:
Singleton(const Singleton &);
Singleton &operator = (const Singleton &);

static T _instance;
};

template<class T> T Singleton<T>::_instance;

#endif

x.hpp#ifndef x_hpp
#define x_hpp

#include <stdio.h>

#include "singleton.hpp"

class X : public Singleton<X>
{
public:
X() : x(0) {}

void foo() { printf("%d\n", x++); }

private:
int x;
};

#endif

bar.cpp#include "x.hpp"

void bar()
{
X::instance()->foo();
}

main.cpp#include "x.hpp"

extern void bar();

int main(int argc, const char *argv[])
{
X::instance()->foo();
bar();

return 0;
}