Поэтому в основном я хочу иметь чисто виртуальный метод, возвращающий итератор в произвольную коллекцию конкретного типа, например, в псевдокоде:
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
был просто для демонстрации, на самом деле это конкретный тип.
Вот основной и очень элементарный подход скелета с использованием стирания типов. Вам придется заполнить много недостающих деталей, хотя!
#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();
Если вы хотите использовать виртуальный метод, вы не можете использовать произвольное возвращаемое значение. Что вы можете сделать, это определить базовый класс, который является оберткой вокруг итераторов, и подкласс из этого класса обертки.
Но даже тогда вы должны ограничить себя наименьшим общим знаменателем, поскольку в стандартной библиотеке C ++ есть несколько классов итераторов.
Так что, AFAICS, такой метод с произвольными итераторами невозможен без использования шаблонов.