It's difficult to have dynamic polymorphism with C++-style iterators. operator++(int)
returns by value, which afaik is intractable: you can't have a virtual member function which returns *this
by value without it being sliced.
If possible, I recommend using templates as everyone else says.
However if you do need dynamic polymorphism, for example because you can't expose the implementation of add_all_msgs as a template would do, then I think you could pretend to be Java, like this:
struct MessageIterator {
virtual Message &get() = 0;
virtual void next() = 0;
// add more functions if you need more than a Forward Iterator.
virtual ~MessageIterator() { }; // Not currently needed, but best be safe
};
// implementation elsewhere. Uses get() and next() instead of * and ++
void add_all_msgs(MessageIterator &it);
template <typename T>
struct Adaptor : public MessageIterator {
typename T::iterator wrapped;
Adaptor(typename T::iterator w) : wrapped(w) { }
virtual Message &get() {
return *wrapped;
}
virtual void next() {
++wrapped;
}
};
int main() {
std::deque<Message> v;
Adaptor<std::deque<Message> > a(v.begin());
add_all_msgs(a);
}
I've checked that this compiles, but I haven't tested it and I've never used this design before. I also haven't bothered with const-ness - in practice you probably want a const Message &get() const
. And at the moment the adaptor has no way of knowing when to stop, but then neither does the code you started with, so I've ignored that too. Basically you'd need a hasNext
function which compares wrapped
against an end iterator supplied to the constructor.
You might be able to do something with a template function and const references, so that the client doesn't have to know about or declare that nasty Adaptor type.
[Edit: come to think of it, it's probably better to have a stub add_all_msgs
function template, that wraps its parameter in an Adaptor and then calls real_add_all_msgs
. This completely hides the adaptor from the client.]