wrap std :: iterator в C ++ - PullRequest
       6

wrap std :: iterator в C ++

4 голосов
/ 06 декабря 2010

Мне нужно обернуть векторный итератор, но мне не нравится идея переписать его с нуля. И я не могу выделить его подкласс, поскольку векторный итератор не является кроссплатформенным. По крайней мере, GNU и IBM выглядят по-разному.

Я хочу сделать следующее:

class MyContainer {
    vector<double> data;
    vector<int> indices;

    iterator
    begin()
    { return my_iterator(data, indices.begin()); }

    iterator
    end()
    { return my_iterator(data, indices.end()); }
}

MyContainer  cont;

Где вектор индексов содержит целочисленные позиции в векторе данных. Предполагается, что данные будут намного больше, чем индексы.

Так что мне нужен итератор, который может проходить через индексы в любом направлении, как итератор нормального вектора, с единственным исключением: он должен возвращать значение вектора данных, когда к нему будет осуществляться доступ. e.g.:

for(MyContainer::iterator it = cont.begin(); it != cont.end(); it++) {
    cout << *it << endl; // values of data should appear here
}

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

любое простое решение?

Ответы [ 3 ]

6 голосов
/ 06 декабря 2010

Есть отличная библиотека Boost для определения пользовательских итераторов.Вам нужно предоставить классу несколько методов:

i.dereference()  Access the value referred to
i.equal(j)       Compare for equality with j
i.increment()    Advance by one position
i.decrement()    Retreat by one position
i.advance(n)     Advance by n positions
i.distance_to(j) Measure the distance to j

Затем вы получите остаток от iterator_facade .

Удачи!

4 голосов
/ 06 декабря 2010

Это очень похоже на permutation_iterator , один из "встроенных" адаптеров из библиотеки Boost.Iterator

См. этот пример (модифицировано из документов Boost) на кодовой панели.

2 голосов
/ 06 декабря 2010

В стандартной библиотеке C ++ ничего нет, но вы, вероятно, можете заставить boost::iterator_adapter делать то, что вы хотите. Предварительный осмотр предполагает, что вам нужно переопределить iterator_adapter::dereference и iterator_adapter::equal.

template <typename _Scalar=double,
          typename _Idx=int, 
          typename _Seq=std::vector<_Scalar>, 
          typename _IdxVector=std::vector<_Idx> >
class SelIter 
    : public boost::iterator_adaptor< SelIter<_Scalar, _Idx>, 
                                      typename _IdxVector::iterator, _Scalar > 
{
public:
    typedef boost::iterator_adaptor< SelIter, typename _IdxVector::iterator, _Scalar > Base;

    SelIter(_Seq& scalars, _IdxVector& idxs);
    SelIter(_Seq& scalars, typename _IdxVector::iterator pi);

    typename Base::reference dereference() const;
    bool equal(const SelIter& x) const;
private:
    // ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...