Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"undefined reference" to static member of template class accessed from static method

I have a static class method that needs access to a pointer MyTypePointer that therefore has to be declared static. Since it is a template class I have to put the methods inside the header file but I can't define MyTypePointer in the header.

So I get the "undefined Reference" error since MyTypePointer is not declared. How can I make this work / declare MyTypePointer.

myclass.h

template <typename A, typename B>
class PathfindingClass {
    typedef std::vector<GenericEdgeClass<A, B>*> MyType;
    static MyType *MyTypePointer;
};

template <typename A, B>
void MyClass<A, B>::MyMethod(int x, int y) { 
    //do something with MyTypePointer
}

Thank you very much.

like image 412
user3049681 Avatar asked Dec 17 '13 18:12

user3049681


3 Answers

It is a late answer for full reference, as this question is linked as a reference to another question.

A minimal broken example of a static field declared but not defined could be :

template<typename T>
class A
{
public:
    static T val;
    static void init()
    {
        val=0;
    }
};

int main()
{
    // A::init();
    A<double>::init();
    return 0;
}

The fix is just to define the static field after the class definition :

template<typename T>
class A
{
public:
    static T val;
    static void init()
    {
        val=0;
    }
};

template<typename T> T A<T>::val; // only change here

int main()
{
    // A::init();
    A<double>::init();
    return 0;
}
like image 94
Serge Ballesta Avatar answered Sep 18 '22 14:09

Serge Ballesta


In the template definition, static MyType *MyTypePointer; declares an object. You still have to define it, outside the template class definition:

template <class A, class B>
typename PathfindingClass<A, B>::MyType*
PathfindingClass<A, B>::MyTypePointer;
like image 41
Pete Becker Avatar answered Sep 20 '22 14:09

Pete Becker


You can still define the template member and explicitly instantiate it for all needed specializations. If you insist in having a state data member of a class template that's roughly what's needed.

Given that global variables share all sorts of problems, including dependency issues during initialization, you are much better off, wrapping you data member by a static member function:

template <typenane T>
class foo {
    // ...
    static X*& member() {
        static X* rc = ...;
        return rc;
    }
};

The local variable is initialized the first time the function is called and a reference to it can safely be used. This approach also works for templates.

Note that I still recommend to avoid global variables! They cause many problems in the long-term and short-term benefit of using them is a huge debt which normally doesn't pay off.

like image 21
Dietmar Kühl Avatar answered Sep 18 '22 14:09

Dietmar Kühl