Расширение векторного итератора для удовлетворения моих потребностей - PullRequest
1 голос
/ 28 сентября 2010

У меня есть один дизайн в одном из моих проектов:

template<typename C> class B {
    int numValue;
    C inner;
}

template<typename C> class A {
    vector<B<C>> container;
    ...
    Iterator InsertItem(C item) {...}
}

Мне нужен способ изменить существующий векторный итератор, чтобы он возвращал итератор, который будет возвращать & inner наразыменование вместо возврата ссылки на объект B.Надеюсь, он не нуждается в полной реализации класса итератора.

Ответы [ 4 ]

2 голосов
/ 28 сентября 2010

Такой итератор - Boost.TransformIterator

Пример (заполнение вашего кода, а не то, что это особенно хороший дизайн).

#include <vector>
#include <iostream>
#include <functional>
#include <boost/iterator/transform_iterator.hpp>
using namespace std;

template<typename C> struct B {
    int numValue;
    C inner;
};

template <class T>
struct get_inner: std::unary_function<B<T>&, T&>
{
    T& operator()(B<T>& value) const { return value.inner; }
};

template<typename C> struct A {
    vector<B<C> > container;
    typedef boost::transform_iterator<get_inner<C>, typename vector<B<C> >::iterator> Iterator;
    Iterator InsertItem(C item) {
        B<C> b = {0, item};
        container.push_back(b);
        return Iterator(--container.end());
    }
};

int main()
{
    A<double> a;
    A<double>::Iterator it = a.InsertItem(3.14);
    std::cout << *it << '\n';
}
1 голос
/ 28 сентября 2010

Я вообще не вижу, где вам нужно модифицировать итератор.Скорее, вам просто нужно добавить несколько функций-членов в B, которые возвращают соответствующие итераторы к внутреннему:

template <class C>
class B { 
    C inner;
public:

    typedef typename C::iterator iterator;
    typedef typename C::const_iterator const_iterator;
    // etc.

    iterator begin() { return inner.begin(); }
    iterator end()   { return inner.end(); }

    // and so on for rbegin, rend, cbegin, cend, ...
};

Редактировать: я должен добавить, что если вы хотите поддержать (для одного примера) back_insert_iterator, выВам также понадобится добавить push_back к B, который вы (вероятно) также осуществите, переместив его в C::push_back.

0 голосов
/ 28 сентября 2010

Используйте boost::transform_iterator, чтобы создать новый итератор, который обернет ваш векторный итератор, но вместо этого выдает значение inner:

template<typename C>
C& getInner(B<C>& b)
{
    return b.inner;
}    

vector<B<C>> container;
typedef boost::transform_iterator<C&(*)(B<C>&), vector<B<C> >::iterator> inner_iterator;
inner_iterator it=boost::make_transform_iterator(container.begin(), getInner<C>)
0 голосов
/ 28 сентября 2010

Если ваш итератор возвращает &inner, как вы будете когда-либо обращаться к numValue?

Если вы создадите свой собственный A :: итератор, должно быть легко иметь его, содержащий vector<B<C>>::iterator ибольшинство операций через это.Да, вам понадобится полная реализация класса итератора, но это не составит труда.

...