Вопрос

Я написал редкий векторный класс (см. #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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top