Max Frai
Max Frai

Reputation: 64286

Static variable with templates

I want to store some additional information about classname during inheritance:

#define CLASS_TO_STRING(name) #name

class IBase {};

template <typename T>
struct BaseManager
{
    static const char* MANAGER_TAG = CLASS_TO_STRING(T);
};

std::map<const char*, IBase*> mManagers;

template <typename T>
void addManager(BaseManager<T>* manager)
{
    mManagers[T::MANAGER_TAG] = manager;
}

So, when I call addManager with some object of type inherited from BaseManager I get an error that BaseManager<TYPENAME>::MANAGER_TAG is undefined. I understand the reason of the problem but can't understand how to resolve it.

Upvotes: 0

Views: 58

Answers (2)

marcinj
marcinj

Reputation: 49986

You can change const char* to constexpr but I am afraid all you will get from CLASS_TO_STRING(T) is T (at least g++ gives me T on output - and thats because preprocessor runs before compilation and template instantiation).

also instead of T::MANAGER_TAG, you should BaseManager<T>::MANAGER_TAG. And your BaseManager should inherit from IBase if :

mManagers[BaseManager<T>::MANAGER_TAG] = manager;

is supposed to work.

The reason you get your error is I suppose that in-class initialization of static data member, works only for const integral types.

Upvotes: 1

peppe
peppe

Reputation: 22744

Apart from marcin_j's comment about in-class initialization (which works only in C++11 and for nonintegral types it requires constexpr), the real problem is this:

static const char* MANAGER_TAG = CLASS_TO_STRING(T);

When this line gets parsed by the preprocessor, CLASS_TO_STRING will turn T into the string literal "T". What's really going on here is that the preprocessor (the one performing macro substitution) has absolutely no idea of the template system and that T is a template parameter. You need a different approach here.

Upvotes: 2

Related Questions