bug-gplusplus
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Template specialization - strange behavior


From: Klaus Barthelmann
Subject: Template specialization - strange behavior
Date: Wed, 04 Feb 2004 13:49:14 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020623 Debian/1.0.0-0.woody.1

Hi!

I am not quite sure whether the following is a bug in g++-3.3.2 or a language feature. (I find Stroustrup's book rather unclear in this respect.) However, it looks very strange.

Let me introduce the well-known stack as an example:

template<class T> class Stack {
   struct Link {
      T item;
      Link* next;
   };
   Link* first;
public:
   Stack() { first = 0; }
   void push(T const& item);
   T pop();
};

It is implemented as a linked list. Now I try to specialize it for pointer types such that they are all derived from a single implementation (for type void*):

template<class T> class Stack<T*> : private Stack<void*> {
public:
   typedef Stack<void*> Base;
   Stack() : Base() { }
   ~Stack() { ~Base(); }
   void push(T* const& item) { Base::push(item); }
   T* pop() { return static_cast<T*>(Base::pop()); }
};

The base class refers to the general template.

This, however, gives an error message:

stack.cc:71: error: base class `Stack<void*>' has incomplete type

It does not help to move the typedef out of the class:

typedef Stack<void*> Base;
template<class T> class Stack<T*> : private Base {
   ...
};

On the contrary, it does help to define a variable (!!):

Stack<void*> dummy;

template<class T> class Stack<T*> : private Stack<void*> {
   // same as above
};

It also helps to introduce a specialization for type void* first:

template<> class Stack<void*> {
   struct Link {
      void* item;
      Link* next;
   };
   Link* first;
public:
   Stack() { first = 0; }
   void push(void* const& item);
   void* pop();
};

However, as long as I do not care to remove the "const&" in the parameter to push (because it is cheaper to copy the pointer), this is exactly the same as the code the compiler should produce from the general template. I think it should be able to figure this out for itself. Is g++ just too lazy?
Best regards
  Klaus

Klaus Barthelmann, Institut f"ur Informatik, Johannes Gutenberg-Universit"at, 55099 Mainz,
eMail: address@hidden,
WWW: htp://www.informatik.uni-mainz.de/~barthel/
template<class T> class Stack {
   struct Link {
      T item;
      Link* next;
   // ~Link() { delete next; }
   };
   Link* first;
public:
   Stack() { first = 0; }
// ~Stack() { delete first; }
   void push(T const& item);
   T pop();
};

template<class T> void Stack<T>::push(T const& item)
{
   Link* list = new Link;
   list->item = item;
   list->next = first;
   first = list;
}

template<class T> T Stack<T>::pop()
{
   Link* list = first;
   first = first->next;
   T item = list->item;
   delete list;
   return item;
}

#ifdef SPECIALIZE

template<> class Stack<void*> {
   struct Link {
      void* item;
      Link* next;
   // ~Link() { delete next; }
   };
   Link* first;
public:
   Stack() { first = 0; }
// ~Stack() { delete first; }
   void push(void* const& item);
   void* pop();
};

void Stack<void*>::push(void* const& item)
{
   Link* list = new Link;
   list->item = item;
   list->next = first;
   first = list;
}

void* Stack<void*>::pop()
{
   Link* list = first;
   first = first->next;
   void* item = list->item;
   delete list;
   return item;
}

#else

//Stack<void*> dummy; //!??

#endif

template<class T> class Stack<T*> : private Stack<void*> {
public:
   typedef Stack<void*> Base;
   Stack() : Base() { }
// ~Stack() { ~Base(); }
   void push(T* const& item) { Base::push(item); }
   T* pop() { return static_cast<T*>(Base::pop()); }
};

reply via email to

[Prev in Thread] Current Thread [Next in Thread]