views:

83

answers:

3

This is difficult for me to formulate in a Google query (at least one that gives me what I'm looking for) so I've had some trouble finding an answer. I'm sure I'm not the first to ask though. Consider a class like so:

template < class T >
class MyClass
{
  private:
    static T staticObject;
    static T * staticPointerObject;
};
...
template < class T >
T MyClass<T>::staticObject; // <-- works
...
template < class T >
T * MyClass<T>::staticPointerObject = NULL; // <-- cannot find symbol staticPointerObject.

I am having trouble figuring out why I cannot successfully create that pointer object.

Edit:

The above code is all specified in the header, and the issue I mentioned is an error in the link step, so it is not finding the specific symbol.

+2  A: 

"Cannot find symbol staticPointerObject" - this looks like a linker error message. Is it? (Details like this have to be specified in your question).

If it is, them most likely it happens because you put the definition(s) of your static member(s) into an implementation file (a .cpp file). In order for this to work correctly, the definitions should be placed into the header file (.h file).

Again, details like this have to be specified in your question. Without them it turns into a random guess-fest.

AndreyT
I updated my original post. It was a linker error.
Anthony
A: 

I have found two solutions. Neither of them are 100% what I was hoping for.

  1. Explicitely initialize the specific instance, e.g.

    int * MyClass<int>::staticPointerObject = NULL;

This is not convinient especially when I have a lot of different types.

  1. Wrap the pointer inside the class, e.g.

    template < class T >   
    class MyClass   
    {   
      private:   
        struct PointerWrapper   
        {   
          T * pointer;   
          PointerWrapper( void )   
            : pointer( NULL )   
          { }   
        };   
        T staticObject;   
        T * staticPointerObject;   
    };   
    ...   
    template < class T >   
    T MyClass<T>::staticObject; // <-- works fine.   
    ...   
    template < class T >   
    MyClass<T>::PointerWrapper MyClass<T>::staticPointerObject; // <-- works fine.

This is a bit of a hassle, but at least usable. Why is it I can instansiate a variable object but not a pointer to a variable object? If anything I would think I'd have more problems the other way around (the compiler knows ahead of time what a pointer looks like, but not what my object looks like).

If someone has a better answer I'd love to see it!

Anthony
A: 

Your first "definition" of static member is but a declaration - here is a quote from the standard.

15 An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. [Note: there is no syntax for the definition of a static data member of a template that requires default initialization. template<> X Q::x; This is a declaration regardless of whether X can be default initialized (8.5). ]

The second definition should work. Are you sure you have everything available in one compilation unit? What is teh exact text of error message?

The following compiles/runs with g++ - all in one file

#include <iostream>

template < class T >
class MyClass
{
  public:
    static T staticObject;
    static T * staticPointerObject;
};

template < class T >
T MyClass<T>::staticObject;

template < class T >
T * MyClass<T>::staticPointerObject = 0; 

int main(int argc, char **argv)
{
  int an_int = 5;
  MyClass<int>::staticPointerObject = &an_int;
  std::cout << *MyClass<int>::staticPointerObject << std::endl;

  char a_char = 'a';
  MyClass<char>::staticPointerObject = &a_char;
  std::cout << *MyClass<char>::staticPointerObject << std::endl;
}
Arkadiy
I'm using a GNU cross compiler for PowerPC 604. The exact output isUndefined symbol: _t16DynamicSingleton1ZQ213SingletonTest12SharedObject$ptr (binding 1 type 0)ld error: Module contains undefined symbol(s) and may be unusable.Originally I had the definition inside of a *.cpp file, but I've since moved it to the header file, so it should definitely be visible.I've found some Google hits that mention having to take the step I mentioned in the first part of my answer below. The compiler I'm using might just not support what I'm trying to do (namely, exactly what you just did).
Anthony
I should mention it is linking with VxWorks 5.5 at this point.
Anthony
Could you demangle the symbol in that error message? My c++filt refuses to do it.
Arkadiy
There is no explicit specialization in the code he shows.
Johannes Schaub - litb