С ++ 11 foreach синтаксис и пользовательский итератор - PullRequest
59 голосов
/ 27 сентября 2011

Я пишу итератор для контейнера, который используется вместо контейнера STL.В настоящее время контейнер STL используется во многих местах с синтаксисом foreach c ++ 11 , например: for(auto &x: C).Нам нужно обновить код, чтобы использовать пользовательский класс, который упаковывает контейнер STL:

template< typename Type>
class SomeSortedContainer{
    std::vector<typename Type> m_data; //we wish to iterate over this
    //container implementation code
};    
class SomeSortedContainerIterator{
    //iterator code
};

Как настроить auto на использование правильного итератора для пользовательского контейнера, чтобы код мог вызываться вследующим образом?:

SomeSortedContainer C;
for(auto &x : C){
    //do something with x... 
}

В общем, что требуется для гарантии того, что auto использует правильный итератор для класса?

Ответы [ 4 ]

51 голосов
/ 27 сентября 2011

У вас есть два варианта:

  • вы предоставляете функции-члены с именами begin и end, которые можно вызывать как C.begin() и C.end();
  • в противном случае,Вы предоставляете бесплатные функции с именами begin и end, которые можно найти с помощью поиска, зависящего от аргумента, или в пространстве имен std, и которые можно вызывать как begin(C) и end(C).
51 голосов
/ 27 сентября 2011

Чтобы иметь возможность использовать диапазон на основе, ваш класс должен предоставить const_iterator begin() const и const_iterator end() const членов. Вы также можете перегрузить глобальную функцию begin, но, на мой взгляд, лучше иметь функцию-член. iterator begin() и const_iterator cbegin() const также рекомендуются, но не обязательны. Если вы просто хотите перебрать один внутренний контейнер, это ДЕЙСТВИТЕЛЬНО просто:

template< typename Type>
class SomeSortedContainer{

    std::vector<Type> m_data; //we wish to iterate over this
    //container implementation code
public:
    typedef typename std::vector<Type>::iterator iterator;
    typedef typename std::vector<Type>::const_iterator const_iterator;

    iterator begin() {return m_data.begin();}
    const_iterator begin() const {return m_data.begin();}
    const_iterator cbegin() const {return m_data.cbegin();}
    iterator end() {return m_data.end();}
    const_iterator end() const {return m_data.end();}
    const_iterator cend() const {return m_data.cend();}
};    

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

class const_iterator : public std::iterator<random_access_iterator_tag, Type>{
    typename std::vector<Type>::iterator m_data;
    const_iterator(typename std::vector<Type>::iterator data) :m_data(data) {}
public:
    const_iterator() :m_data() {}
    const_iterator(const const_iterator& rhs) :m_data(rhs.m_data) {}
     //const iterator implementation code
};

Подробнее о написании класса итератора см. мой ответ здесь .

7 голосов
/ 11 января 2013

Как уже говорили другие, ваш контейнер должен реализовывать функции begin() и end() (или иметь глобальные или std:: функции, которые принимают экземпляры вашего контейнера в качестве параметров).

Эти функции должны возвращатьтого же типа (обычно container::iterator, но это только соглашение).Возвращаемый тип должен реализовывать operator*, operator++ и operator!=.

2 голосов
/ 27 сентября 2011

Насколько мне известно SomeSortedContainer просто нужно предоставить begin() и end().И они должны возвращать стандартный совместимый прямой итератор, в вашем случае SomeSortedContainerIterator, который фактически обернул бы std::vector<Type>::iterator.Под стандартным соответствием я подразумеваю, что он должен предоставлять обычные операторы инкремента и разыменования, а также все те value_type, reference_type, ... typedefs, которые, в свою очередь, используются конструкцией foreach для определения базового типа контейнера.элементы.Но вы можете просто переслать их из std::vector<Type>::iterator.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...