virtual template<class U> operator Handle<U>* () const =0;
Виртуальная функция шаблона не разрешена спецификацией языка.
Рассмотрим этот код на ideone , а затем проследим ошибку компиляции:
ошибка: шаблоны не могут быть «виртуальными»
Что теперь вы можете сделать?Одним из решений является следующее:
template<class T>
class Handle {
public:
typedef typename T::super super; //U = super, which is a superclass of T.
virtual ~Handle () {}
virtual T & operator* () const = 0;
virtual T * operator-> () const = 0;
//not a template now, but still virtual
virtual super operator Handle<super> () const = 0;
};
То есть определите typedef
базового класса в производном классе и используйте его в Handle
.Примерно так:
struct Base {//...};
struct Derived : Base { typedef Base super; //...};
Handle<Derived> handle;
Или вы можете определить черты, как:
struct Base {//... };
struct Derived : Base { //... };
template<typename T> struct super_traits;
struct super_traits<Derived>
{
typedef Base super;
};
template<class T>
class Handle {
public:
typedef typename super_traits<T>::super super; //note this now!
virtual ~Handle () {}
virtual T & operator* () const = 0;
virtual T * operator-> () const = 0;
//not a template now, but still virtual
virtual super operator Handle<super> () const = 0;
};
На мой взгляд, super_traits
является превосходным решением, так как вы определяетечерты производных классов без их редактирования.Кроме того, вы можете определить столько typedef, сколько захотите;скажем, ваш производный класс имеет более одной базы, вы можете определить множество typedef, или, предпочтительно, typelist .