Проблемы наследования с шаблонными классами

У меня проблемы с очень странной ошибкой в ​​написанном мной коде. Основная идея кода может быть упрощена в следующем примере:


template <class f, class g> class Ptr;

template <class a, class b, class c = Ptr<a,b> > class Base { public: Base(){}; };

template <class d, class e> class Derived : public Base <d,e> { public: Derived(){}; };

template <class f, class g> class Ptr { public: Ptr(){}; Ptr(Base<f,g,Ptr<f,g> >* a){}; };

typedef Derived<double,double> DDerived;

int main() { Base<int,int> b = Base<int,int>(); Derived<double,double> d = Derived<double,double>(); DDerived dd = DDerived(); Ptr<double,double> p(&dd); return 1; }

Основная идея состоит в том, что указатели заменяются классом Ptr (в конечном итоге он будет использоваться в настройке MPI, поэтому стандартные указатели фактически бесполезны). Указатели предназначены для «указания» на базовый класс и поэтому могут указывать на любой унаследованный класс (как показано в примере).

Может ли кто-нибудь придумать какую-либо причину, по которой это может не сработать в нетривиальном случае (но в случае, когда архитектура объекта остается идентичной).

Ошибка, возникающая в основном случае, выглядит следующим образом:


void function()
{
  vector nVector(1);  // cut down for simplicity
  nVector[0].SetId(1); // To ensure the node is instantiated correctly
  Ptr temp(&nVector[1]);
};

Этот код выдает ошибку (слегка расширенную версию) при компиляции MPICXX:
без соответствующей функции для вызова Ptr&lt;double, double>::Ptr(Derived&lt;double, double>*)
кандидатов. . . (Некоторые удалены для простоты)
Ptr&lt;f, g>::Ptr(Base&lt;f, g, Ptr&lt;f, g> >*) [with f = double, g = double]

Привет, Эд

EDITED (детализация ошибки немного лучше, добавлена ​​информация о компиляторе)

Ответов (3)

Решение

К сожалению, я был немного глуп и забыл поместить свой класс Ptr в то же пространство имен, что и классы Base и Derived.

Думаю, поэтому он не работал! знак равно

Хорошо, что насчет этого:

class BasePtr
{
public:
    virtual void* obj() = 0;
};

template <class T>
class Ptr :: public BasePtr
{
public:
    Ptr() : ptr(0) {};
    Ptr(T* a) : ptr(a) {};
    virtual T* obj() { return ptr; }
protected:
    T* ptr;
};

Используйте BasePtr в базовом классе, но передайте ему правильный объект шаблона, когда Base необходимо его использовать.

template <class a, class b >
class Base
{
public:
    Base(){};
    void set_ptr( BasePtr* );
};

DDerived dd = DDerived();
Ptr<double,double> p(&dd);
dd.set_ptr( p );

Я все еще не совсем понимаю вашу проблему, но надеюсь, что это поможет.

Попробуйте использовать параметр шаблона шаблона вместо значения по умолчанию.

template <class a, class b, template <class aa, class bb> class c = Ptr >
class Base
{
typedef Ptr<a, b> pointer;
public:
    Base(){};
};