Как заставить шаблонные классы сохранить наследство? - PullRequest
0 голосов
/ 05 мая 2018

Ниже приведен упрощенный код, демонстрирующий мою идею.

#include <iostream> 

struct base {
    virtual int test(){return 0;}
};

struct derived : public base {
    virtual int test(){return 1;}
};

template <typename T>
struct foo : public T {
    virtual int  bar() { return 2;}
};


typedef foo<base> foo_base;
typedef foo<derived> foo_derived;

int main(int argc, char ** argv) {

base * p = new derived(); //It is OK.
std::cout<<p->test()<<std::endl;

foo_base * foo_p = new foo_derived(); //It is not OK 
std::cout<<foo_p->bar()<<std::endl;

foo_base * foo_p2 =(foo_base *)(new foo_derived()); //It is working 
std::cout<<foo_p2->bar()<<std::endl;

delete foo_p2;
delete foo_p;
delete p;

return 0;
}

Я знаю, что это не нормально из-за того, что шаблон изменяет наследование классов. Есть ли элегантный способ сохранить наследство после применения шаблона?

В частности, возможно ли построить наследование между foo<base> и foo<derived>, например, с помощью некоторых шаблонов прокси или специального шаблона, например CRTP, для восстановления того же наследства после создания экземпляра шаблона?

1 Ответ

0 голосов
/ 12 мая 2018

Как сказал Сэм Варшавчик в комментариях, вы не можете полностью автоматизировать этот процесс, поскольку C ++ не имеет отражения и, следовательно, не может перечислить базовые классы. Тем не менее, вы уже пошли по пути typedef создания экземпляров вашего шаблона, и это идеальное место для самостоятельного составления списка базовых классов (ханги выделены в комментариях):

struct base {
    // Don't forget the virtual destructor for polymorphic destruction
    virtual ~base() = default;

    virtual int test() const { return 0; }
};

struct derived : base {
    int test() const override { return 1; }
};

// U... is the list of thebase classes for T
template <typename T, typename... U>
struct foo : T, foo<U>... {
    //        ^^^^^^^^^^^ Inheritance is mirrored here

    virtual int bar() const { return 2; }
};

// base has no base class
typedef foo<base> foo_base;

// derived has one base class, base.
typedef foo<derived, base> foo_derived;

Живой пример на Coliru

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...