If you want to keep it almost like it is now, i.e. if you want runtime polymorphism, the concept of any_iterator
comes to mind.
You can define a special polymorphic iterator which abstracts from both the underlying container and the underlying type. Here is a little snippet to get the idea (it misses some methods to be consider a proper iterator, but shouldn't be difficult to implement the rest by yourself)
template<class T>
class any_input_iterator : public std::iterator< std::input_iterator_tag,T> {
public:
any_input_iterator() {}
any_input_iterator(const any_input_iterator & other) : piter(other.piter->clone()) {}
template<class Iter>
any_input_iterator(Iter iter) : piter( new iterator_impl<Iter>(iter)) {}
T& operator*() {return piter->reference();}
bool operator==(const any_input_iterator & other) const {
if ( typeid(*piter) != typeid(* other.piter) ) return false;
return piter->equal(*other.piter);
}
any_input_iterator& operator++() {piter->advance(); return *this;}
private:
struct iterator_base {
iterator_base() {}
virtual ~iterator_base() {}
virtual void advance() = 0;
virtual T& reference() = 0;
virtual iterator_base* clone() = 0;
virtual bool equal(const iterator_base & other) const = 0;
};
template<class InputIterator> struct iterator_impl : public iterator_base{
iterator_impl(InputIterator t) : m_iter(t) {}
virtual void advance() { ++m_iter;}
virtual T& reference() { return *m_iter;} //assuming this is implicitly castable to T&
virtual iterator_base* clone() {return new iterator_impl(m_iter);}
virtual bool equal(const iterator_base & other) const {
return m_iter == dynamic_cast<const iterator_impl&>(other).m_iter;
}
InputIterator m_iter;
};
std::unique_ptr<iterator_base> piter;
};
Since your algorithms can not know at compile time which is the exact type on which they operate, standard iterators are of little use. Writing your algorithm in terms of this kind-of proxy iterator solves the problem.
Moreover, in my opinion is just a bad idea to write algorithms in terms of container instead of iterator pairs. I'd refactor the code in terms of iterator pairs, but if you still want to stick with vectors, you can make use of any_iterator
to write an any_vector_reference
class.
All these things will work only if you have sequences of the same type (if you don't, you have to work with vector of pointers).