Абстрактный итератор для базовых коллекций

Поэтому в основном я хочу иметь чисто виртуальный метод, возвращающий итератор в произвольную коллекцию конкретного типа, например, в псевдокоде:

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

Пользователю этого класса на самом деле все равно, какую реализацию использует дочерний класс. Это может быть набор, вектор, список, массив и т. Д.

Я знаю о std::iterator класс, но я не могу найти способ указать его правильно, чтобы работать с простым вектором.

virtual std::iterator<std::random_access_iterator_tag,T> getIterator() const = 0;

myVector.begin() // compilation error in implementation

определяющий std::iterator с const T как параметр типа тоже не сработал. Я тоже пыталась уйти T и вместо этого определяя указатель и ссылочные типы как const T* а также const T&,

Взглянув на std::vector реализация, я узнал, что std::vector::const_iterator на самом деле происходит от _Iterator012 вытекающий из _Iterator_base,

Меня действительно беспокоит, что в std нет никакого способа работать с произвольными коллекциями.
Реализация моих классов в виде шаблонов, как в <algorithm> это не вариант для меня по двум причинам:

  • Нет контроля над типом фактического значения
  • Я просто не хочу, чтобы мои шаблоны классов сильно усложняли мой дизайн и делали вещи менее гибкими.

Используемый параметр типа T был просто для демонстрации, на самом деле это конкретный тип.

5

Решение

Вот основной и очень элементарный подход скелета с использованием стирания типов. Вам придется заполнить много недостающих деталей, хотя!

#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(); }
};

Использование:

std::vector<int> v;
std::deque<int> dq;

TEIterator<int> a = v.begin(), b = dq.end();
4

Другие решения

Если вы хотите использовать виртуальный метод, вы не можете использовать произвольное возвращаемое значение. Что вы можете сделать, это определить базовый класс, который является оберткой вокруг итераторов, и подкласс из этого класса обертки.

Но даже тогда вы должны ограничить себя наименьшим общим знаменателем, поскольку в стандартной библиотеке C ++ есть несколько классов итераторов.

Так что, AFAICS, такой метод с произвольными итераторами невозможен без использования шаблонов.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector