У меня есть разные типы, скажем A
, B
, C
, которые все наследуют от некоторого базового класса Base
:
class Base { ... };
class A : public Base { ... };
class B : public Base { ... };
class C : public Base { ... };
Мне нужен контейнер, назовем его Master
, который содержит указатели на объекты типов A
, B
и C
. Я хочу, чтобы контейнер Master
предоставлял итератор для всех содержащих Base
объектов, а также специально типизированные итераторы для всех содержащих A
, B
и C
объектов. В качестве бэкэнда хранилища я буду использовать std::vector
, но было бы неплохо, если бы его потом можно было легко включить.
Концептуально, это интерфейс, который Master
должен представить внешнему миру:
class Master {
public:
add(A *a);
add(B *b);
add(C *c);
remove(Base *base);
iterator<A*> a_begin();
iterator<A*> a_end();
iterator<B*> b_begin();
iterator<B*> b_end();
iterator<C*> c_begin();
iterator<C*> c_end();
iterator<Base*> base_begin();
iterator<Base*> base_end();
// also: reverse iterators, const iterators, reverse const iterators
};
Интерфейс не обязательно должен соответствовать этому точному синтаксису. Например, someMaster.begin<A>()
тоже отлично подходит.
Проблема в том, что даже в этом упрощенном интерфейсе вы уже можете наблюдать некоторое дублирование кода. Это намного хуже в реализации. Это неприемлемо, потому что я хочу иметь возможность позже легко расширять контейнер Master
, если я хочу добавить классы D
, E
и F
(также наследуемые от Base
). Желательно, чтобы я расширил его всего одной или двумя строками кода.
Все это может быть реализовано с большим количеством dynamic_cast
ing, но это ужасно. Я думаю, что некоторая магия с шаблонами и множественным наследованием может помочь мне здесь. Что будет самой чистой реализацией этого класса?