Рекомендации по классу итератора

У меня красный черное дерево реализовано в C++. Он поддерживает функциональность карты STL. Узлы дерева содержат ключи и сопоставленные значения. Я хочу написать итератор класс для этого, но я застрял с тем, как это сделать. Должен ли я сделать это внутренний класс класса дерево? Может ли кто-нибудь дать мне некоторые рекомендации о том, как написать его + некоторые ресурсы??

Спасибо!!

3 ответов


конечно, прочитайте эту хорошую статью о написании итераторов STL, это может дать вам необходимый обзор:

http://www.drdobbs.com/184401417

В общем, да, внутренний класс хорош, потому что итератору нужен доступ к вашей реализации конкретных узлов дерева:

struct container { ...
public:
  struct iterator {
    // these typedefs are needed if you want to be STL compatible
    typedef std::forward_iterator_tag iterator_category;
    typedef T         value_type;
    typedef T*        pointer;
    typedef T&        reference;
    typedef size_t    size_type;
    typedef ptrdiff_t difference_type;

    // the element points to your implementation node
    iterator( element* init = 0 ) : current(init) {}
    T& operator*() { return current->data; } // dereference
    const T& operator*() const { return current->data; }
    iterator& operator++() { // prefix
      if ( current ) current = current->next;
      return *this;
    }
    iterator operator++(int) { // postfix
      iterator temp = *this;
      ++*this;
      return temp;
    }
    bool operator==(const iterator& x) const { return current == x.current; }
    bool operator!=(const iterator& x) const { return current != x.current; }

  private:
    // the element points to your implementation node
    element* current;
  }
  ...

хорошо, что, хотя итератор является общедоступным, элемент все еще может оставаться частным :). И да, код выше STL compilant тоже!


класс итератора должен быть либо вложенным классом, либо, по крайней мере, typedef, который псевдонимы your_map::iterator к некоторому типу, который определен в другом месте. Вложенный класс обычно является самым чистым / простым маршрутом.

что касается ресурсов, одним из возможных источников помощи будет Boost:: iterator библиотека, которая включает компоненты, предназначенные для упрощения реализации итераторов.


Я думал, что добавлю свой собственный небольшой совет.

первое, что я хотел бы отметить, это iterator и const_iterator очень вероятно, что их реализация будет иметь много общего. Однако, несмотря на то, что их код похож, он не совсем идентичен. Это требует шаблонов.

второе, что я хотел бы отметить, это const_iterator должно быть конструктивным из iterator (неявно), но не наоборот.

третье, что я бы хотелось отметить, что если вы хотите иметь map-подобный интерфейс, тогда вам нужно предоставить reverse_iterator и const_reverse_iterator как хорошо.

С точки зрения стиля, я, как правило, не ставят реализацию iterator сам прямо в классе. Я нахожу его нечитаемым, когда реализация класса загромождена таким количеством кода, что вам трудно увидеть доступные типы и методы. По этой причине я бы рекомендовал поместить реализацию вне класса.

наконец, Я определенно рекомендую увеличить.Итератор. Вы можете не использовать его, но читать материал, это особенно даст вам представление о том, как написать код один раз и использовать его для 4 видов!

быстрая иллюстрация:

namespace detail {
  template <class Value> class base_iterator;
}

template <class Value>
class container
{
public:
  typedef detail::base_iterator<Value> iterator;
  typedef detail::base_iterator<Value const> const_iterator;

  typedef boost::reverse_iterator<iterator> reverse_iterator;
  typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
};

Я не знаю о вас, но я чувствую себя хорошо, когда я делаю только четверть работы и использует компилятор/библиотека, чтобы заполнить остальные для меня :)