Использование Boost :: Iterator
-
26-09-2019 - |
Вопрос
Я написал редкий векторный класс (см. #1, #2.)
Я хотел бы предоставить два вида итераторов:
Первый набор, регулярные итераторы, могут указывать на любом элементе, настроен или неселен. Если они считываются, они возвращают либо заданное значение, либо value_type()
, Если они написаны, они создают элемент и верните ссылку на Lvalue. Таким образом, они являются:
Итератор прохождения случайного доступа а также Удобочитаемый а также Пишет Итератор
Второй набор, редкие итераторы, повторяющиеся только на множестве элементы. Поскольку им не нужно лениво создавать элементы, которые написаны, они:
Итератор прохождения случайного доступа а также Удобочитаемый а также Пишет а также Львале Итератор
Мне также нужны Const Versions из обоих, которые не являются пищевыми.
Я могу заполнить пробелы, но не уверен, как использовать Boost :: Iterator_adaptor, чтобы начать.
Вот что у меня сейчас:
template<typename T>
class sparse_vector {
public:
typedef size_t size_type;
typedef T value_type;
private:
typedef T& true_reference;
typedef const T* const_pointer;
typedef sparse_vector<T> self_type;
struct ElementType {
ElementType(size_type i, T const& t): index(i), value(t) {}
ElementType(size_type i, T&& t): index(i), value(t) {}
ElementType(size_type i): index(i) {}
ElementType(ElementType const&) = default;
size_type index;
value_type value;
};
typedef vector<ElementType> array_type;
public:
typedef T* pointer;
typedef T& reference;
typedef const T& const_reference;
private:
size_type size_;
mutable typename array_type::size_type sorted_filled_;
mutable array_type data_;
// lots of code for various algorithms...
public:
class sparse_iterator
: public boost::iterator_adaptor<
sparse_iterator // Derived
, typename array_type::iterator // Base (the internal array)
, value_type // Value
, boost::random_access_traversal_tag // CategoryOrTraversal
> {...}
class iterator_proxy {
???
};
class iterator
: public boost::iterator_facade<
iterator // Derived
, ????? // Base
, ????? // Value
, boost::?????? // CategoryOrTraversal
> {
};
};
Кроме того, это незаконно?
typedef boost::reverse_iterator<sparse_iterator> reverse_sparse_iterator;
Решение
Я не уверен, что вы действительно хотите использовать iterator_adaptor
В вашем случае - вы можете использовать iterator_facade
вместо.
Более тщательное объяснение: iterator_adaptors
используются, когда у вас есть существующий итератор (скажем std::list<int>::iterator
) и хочу повторно использовать свое поведение для вашего итератора, например. Ваш итератор вернется в два раза больше значений, что находится в списке, но повторно использовать код обхода из оригинального итератора. Или наоборот: вы можете захотеть итератор, который пропустит некоторые элементы в исходном списке, но возвращает значения без изменений. Я не уверен, хочу ли вы основывать свой итератор (как в повторном использовании кода) после итераторы ваших базовых структур, но говоря для меня, я бы не особо в случае неработающего итератора, как вы, вероятно, захотите создать некоторые прокси для справки, которая означает, что вы не можете использовать любой базовый итератор dereference()
код, а обход, вероятно, легко. Вы можете, однако, база свой sparse_iterator
На некоторых итераторе, который вытесняет на самом деле существующие элементы массива, если хотите.
Есть проблемы с прокси-подходом, поэтому не ожидайте, что он не работает безупречно, не проходя через много обручей. Для одной вещи, версия NONSPARSE ITERATORT value_type()
, что означает выражения, как iter->foo()
следует перевести на value_type().foo()
Если соответствующая запись не существует. Но это ставит трудность, что pointer_proxy::operator->()
должен что-то вернуть с operator->
, желательно указатель (определенно не value_type()
). Что приводит к валютному вопросу: указатель на что? Есть возможности решить это (для одного, если у вас есть ваши объекты, управляемые boost::shared_pointer
, вы можете просто вернуть shared_pointer
к А. new
«Экземпляр).
Для неработающего итератора необходимо реализовать:
class reference_proxy
с участиемreference_proxy::operator&
(Это, вероятно, вернет указатель прокси)reference_proxy::operator value_type&()
для const используетreference_proxy::operator const value_type&()
Для не-Const используетreference_proxy::foo()
для любогоfoo()
Функция участника real_type (в противном случае выражения, как(*it).foo()
AFAIK не будет работать)class pointer_proxy
с участиемpointer_proxy::operator*
(Вернуть ссылку на ссылку)pointer_proxy::operator->
(Сделайте что-то разумное, см. Выше)
Параметры к шаблону фасада итератора должны быть:
Reference
: тоreference_proxy
Pointer
: тоpointer_proxy
Редкая версия проще: если основной итератор имеет разумное (т. Е. Соответствует желаемому поведению) и правильно реализовано, вы можете просто опускать параметры iterator_adaptor
(За исключением первых двух) и принять всю реализацию.
Проблема «не сознает»: вставить typename
.