Рекомендации по классу итератора
У меня красный черное дерево реализовано в 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;
};
Я не знаю о вас, но я чувствую себя хорошо, когда я делаю только четверть работы и использует компилятор/библиотека, чтобы заполнить остальные для меня :)