I have different types, say A, B, C, that all inherit from some base class Base:
class Base { ... };
class A : public Base { ... };
class B : public Base { ... };
class C : public Base { ... };
I need a container, let’s call it Master, that holds pointers to objects of types A, B and C. I want the Master container to provide an iterator over all contained Base objects, as well as specifically-typed iterators over all contained A, B and C objects. As a storage backend, I’ll be using std::vector, but it would be nice if this can be switched easily later on.
Conceptually, this is the interface that Master should present to the outside world:
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
};
The interface does not have to match this precise syntax. For example, someMaster.begin<A>() is perfectly fine too.
The trouble is, even in this simplified interface, you can already see some code duplication happening. It’s much worse in the implementation. This is unacceptable, because I want to be able to extend the Master container easily later on, if I want to add classes D, E and F (also inheriting from Base). Preferably, I would like to extend it with just one or two lines of code.
All this could be implemented with lots of dynamic_casting, but that’s ugly. I think some magic with templates and multiple inheritance could help me out here. What would be the cleanest implementation of this class?
Here’s a sketch of what I would do:
That leaves you to implement
my_type_list(rather simple),derive_from(not as simple, but not too hard either), andmy_assembling_iterator(I hadn’t had a need to do something like that yet).You can find a working C++03 type list implementation here. It only takes up to nine template arguments (but that’s easily extended), and you’ll have to write
but it’s simple and free and I know it works (because I’m using this library myself).
The
derive_fromtemplate would look something like this:That leaves the iterator. What are your needs regarding it? Does it have to be a random-access iterator (hard) or would a forward iterator suffice? Do you need any particular order to iterate over the elements?