Abstract iterator for basic collections

So, basically, I want a pure virtual method to return an iterator to an arbitrary set of a specific type, for example, in pseudocode:

virtual Iterator<T> getIterator() const = 0; 

The user of this class does not really care what implementation the child class uses. It can be a set, vector, list, array, etc.

I know the std::iterator class, but I cannot find a way to specify it correctly to work with a simple vector.

 virtual std::iterator<std::random_access_iterator_tag,T> getIterator() const = 0; myVector.begin() // compilation error in implementation 

defining std::iterator with const T , since the type parameter does not work either. I also tried to leave T and instead define the pointer and reference types as const T* and const T& .

Looking at the implementation of std::vector , I found that std::vector::const_iterator actually comes from _Iterator012 from _Iterator_base .

It really seems to me that there is no way to work with arbitrary collections in std. Implementing my classes as templates, such as <algorithm> , is not an option for me for two reasons:

  • There is no control over the type of actual value
  • I just don’t want my class templates to complicate my design significantly and make things less flexible.

The parameter T was just for demonstration, in fact it is a specific type.

+4
source share
2 answers

Here is a basic and very rudimentary skeletal approach using style erasure. You will need to fill in a lot of missing details though!

 #include <memory> template <typename T> class TEIterator { struct TEImplBase { virtual ~TEImplBase() { } virtual std::unique_ptr<TEImplBase> clone() const = 0; virtual void increment() = 0; virtual T & getValue() = 0; T * getPointer() { return std::addressof(getValue()); } }; template <typename Iter> struct TEImpl { Iter iter; TEImpl(Iter i) : iter(i) { } virtual T & getValue() { return *iter; } virtual std::unique_ptr<TEImplBase> clone() const { return std::unique_ptr<TEImplBase>(new TEImpl<Iter>(*this)); } virtual void increment() { ++iter; } }; std::unique_ptr<TEImplBase> impl; public: template <typename T> TEClass(T && x) : impl(new TEImpl<typename std::decay<T>::type>(std::forward<T>(x))) { } TEClass(TEClass && rhs) = default; TEClass(TEClass const & rhs) : impl(rhs.impl.clone()) { } TEIterator & operator++() { impl->increment(); return *this; } T & operator*() { return impl->getValue(); } T * operator->() { return impl->getPointer(); } }; 

Application:

 std::vector<int> v; std::deque<int> dq; TEIterator<int> a = v.begin(), b = dq.end(); 
+4
source

If you want to use a virtual method, you cannot use an arbitrary return value. What you can do is define a base class, which is a wrapper around iterators and a subclass of this wrapper class.

But even then you should limit yourself to the smallest common denominator, since there are several classes of iterators in the C ++ standard library.

So AFAICS, such a method with arbitrary iterators is actually impossible without using templates.

0
source

All Articles