Шаблоны C ++ и виртуальное наследование

Скажем, у меня есть иерархия классов:

class Animal;
class Cat: public Animal;
class Dog: public Animal;

Эти классы не являются шаблонами. У меня есть другая параллельная иерархия шаблонных классов:

template<class T> class Drawer;
template<class T> class CatDrawer: public Drawer<T>;
template<class T> class DogDrawer: public Drawer<T>;

Я хотел бы написать следующее:

class Animal{
template<class T>
virtual shared_ptr<Drawer<T>> create_drawer() = 0;
};

позволить каждому из производных классов создать свою шаблонную версию.

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

Я посмотрел на следующие варианты:

1) я мог шаблон Animal сам:

template<class T>
class Animal{
virtual shared_ptr<Drawer<T>> create_drawer() = 0;
};

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

2) Любопытно рекурсивный шаблон. Я чувствую, что это может сработать, однако это помешает мне создать контейнер указателей на Animal,

3) использовать посетителя; это позволило бы отделить звонок create_drawer() в двух частях, одна на Animal который бы записал тот факт, что мы хотим создать ящик& и один на посетителя, который будет создавать шаблонный ящик не виртуальным способом.

class Animal{
virtual void accept(DrawerCreatorVisitor v) = 0;
};
class Dog: public Animal{
virtual void accept(DrawerCreatorVisitor v){
v.visit(*this);
};
}
...
class DrawerCreatorVisitor{
public:
template<class T>
shared_ptr<Drawer<T>> make_drawer(Animal& animal){
animal.accept(*this); // double dispatch which will set the to_create member
if(to_create == _dog)
return shared_ptr<Drawer<T>>(new DogDrawer<T>(static_cast<Dog&>(animal)));
if(to_create == _cat)
return shared_ptr<Drawer<T>>(new CatDrawer<T>(static_cast<Cat&>(animal)));
};

void visit(Dog dog){
to_create = _dog;
};
void visit(Cat cat){
to_create = _cat;
};
private:
enum Drawable {_dog, _cat};
Drawable to_create;
};

Это похоже на работу; синтаксис вызова в порядке:

DrawerCreatorVisitor dcv;
shared_ptr<Drawer<int>> dcv.make_drawer<int>(the_dog);

Можете ли вы увидеть какой-либо недостаток / любой способ улучшить это? Кроме того, я действительно не нашел нагрузки на предмет, означает ли это, что мой первоначальный дизайн неверен? Большое спасибо 🙂

2

Решение

Задача ещё не решена.

Другие решения


По вопросам рекламы [email protected]