views:

60

answers:

2

Imagine the following template class (setter and getter for the member _t omitted):

template<class T>
class chain
{
public:
  static chain<T> NONE;

  chain()
   : _next(&NONE)
  {}

  ~chain() {}

  chain<T>& getNext() const
  {
    return *_next;
  }

  void setNext(chain<T>* next)
  {
    if(next && next != this)
      _next = next;
  }

  chain<T>& getLast() const
  {
    if (_next == &NONE)
      return *this;
    else
      return _next->getLast();
  }

private:
  T _t;
  chain<T>* _next;
};

The basic idea of this concept is, instead of using null-pointers, I have a static default element that takes in this role while still being a technically valid object; this could prevent some of the issues with null pointers while making the code more verbose at the same time...

I can instantiate this template just fine, but the linker gives an unresolved-external error on the static member object NONE.

I would have assumed that when instantiating the template, the line static chain<T> NONE; would effectively be a definition, too, as it actually happens within the implementation instantiating the template. However, it turns out not to be...

My question is: is something like possible at all, and if so, how, without explicitly defining the NONE element before each and every template instantiation?

+3  A: 

You still need to define that outside the class just like a non-template class. Just like in a non-template class, you have only declared NONE inside the class definition and still need to define it:

template<class T>
class chain
{
    // the same as your example
};

// Just add this
template <class T>
chain<T> chain<T>::NONE;
R Samuel Klatchko
Ah, I see you can actually define the static member while still being templated. It would just have been a hassle to have to do it for every instantiation, but your solution is perfect.
Mephane
+2  A: 
template < typename T >
chain<T> chain<T>::NONE;

should work

Noah Roberts