fferri
fferri

Reputation: 18950

Static member definition of template superclass

I need to associate the instances of (several) class(es) to small integers, which I call handles.

I'd hate doing this using preprocessor macros, so I thought I'd use templates and multiple inheritance.

I defined a Handle class like this:

#include <map>

template<typename Key, typename Self>
class Handle
{
protected:
    static Key nextHandle;
    static std::map<Key, Self*> handles;
    Key handle;
public:
    Handle()
    {
        handles[nextHandle++] = this;
    }

    virtual ~Handle()
    {
        handles.erase(handle);
    }

    static Self * byHandle(Key handle)
    {
        typename std::map<Key, Self*>::const_iterator it = handles.find(handle);
        if(it == handles.end())
            return nullptr;
        else
            return it->second;
    }

    Key getHandle()
    {
        return handle;
    }
};

and the usage of this "pattern" would be:

class Test : public SomeSuperclass, ... , public Handle<int, Test>
{
public:
    Test();
};

Test::Test()
    : Handle()
{
}

int Handle<int, Test>::nextHandle = 666;
std::map<int, Test*> Handle<int, Test*>::handles;

the problem is here ^^^ I don't know how to define the storage for those static variables, I get this error from clang++:

handle_test.cpp:17:24: error: template specialization requires 'template<>'

int Handle::nextHandle = 666;

or, if I try do define it in the Test class, such as:

int Test::nextHandle = 666;
std::map<int, Test*> Test::handles;

I get this other error:

handle_test.cpp:20:11: error: no member named 'nextHandle' in 'Test'

int Test::nextHandle = 666;

Upvotes: 1

Views: 51

Answers (1)

songyuanyao
songyuanyao

Reputation: 173014

If you want static member definition of template specialization, you could:

template<>
int Handle<int, Test>::nextHandle = 666;
template<>
std::map<int, Test*> Handle<int, Test>::handles;

If you want static member definition of primary template, you could:

template<typename Key, typename Self>
Key Handle<Key, Self>::nextHandle;
template<typename Key, typename Self>
std::map<Key, Self*> Handle<Key, Self>::handles;

You couldn't define them on derived class Test, they're members of Handle.

Upvotes: 2

Related Questions