如何以优雅高效的方式实现各种迭代器类别
How can I implement various iterator categories in an elegant and efficient way?
我正在实现STL容器,例如vector。让我感到困惑的是迭代器的实现。
如果我想实现所有迭代器类别:input_iterator、output_iterator、forward_iterator、bidirectional_iterator和random_access_iterator。
如何管理他们的继承关系?我已经阅读了如何实现 STL 风格的迭代器并避免常见的陷阱?-Mooing Duck's Answer
这是他象征性的例子:
iterator {
iterator(const iterator&);
~iterator();
iterator& operator=(const iterator&);
iterator& operator++(); //prefix increment
reference operator*() const;
friend void swap(iterator& lhs, iterator& rhs); //C++11 I think
};
input_iterator : public virtual iterator {
iterator operator++(int); //postfix increment
value_type operator*() const;
pointer operator->() const;
friend bool operator==(const iterator&, const iterator&);
friend bool operator!=(const iterator&, const iterator&);
};
//once an input iterator has been dereferenced, it is
//undefined to dereference one before that.
output_iterator : public virtual iterator {
reference operator*() const;
iterator operator++(int); //postfix increment
};
//dereferences may only be on the left side of an assignment
//once an input iterator has been dereferenced, it is
//undefined to dereference one before that.
forward_iterator : input_iterator, output_iterator {
forward_iterator();
};
//multiple passes allowed
bidirectional_iterator : forward_iterator {
iterator& operator--(); //prefix increment
iterator operator--(int); //postfix decrement
};
random_access_iterator : bidirectional_iterator {
friend bool operator<(const iterator&, const iterator&);
friend bool operator>(const iterator&, const iterator&);
friend bool operator<=(const iterator&, const iterator&);
friend bool operator>=(const iterator&, const iterator&);
iterator& operator+=(size_type);
friend iterator operator+(const iterator&, size_type);
friend iterator operator+(size_type, const iterator&);
iterator& operator-=(size_type);
friend iterator operator-(const iterator&, size_type);
friend difference_type operator-(iterator, iterator);
reference operator[](size_type) const;
};
但我发现了一个问题:如果我有一个来自类 random_access_iterator
a
的实例,我使用代码random_access_iterator b = a + 1
。这将导致编译错误。因为a + 1
的类是基础iterator
,而不是random_access_iterator
。
所以我不认为这是一个合理的解决方案。
我是不是误会了?或者请告诉我一种优雅而有效的实现方式。
谢谢
我认为你应该使用CRTP(https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)。喜欢这个:
template <typename T, typename ItT>
struct iiterator_t {
typedef T value_type;
typedef T& reference;
typedef T* pointer;
typedef ItT iterator_type;
virtual iterator_type& operator=(const iterator_type&) = 0;
virtual iterator_type& operator++() = 0;
virtual reference operator*() const = 0;
};
template <typename T, typename ItT>
struct iterator_impl_t : virtual public iiterator_t<T, ItT>{
typedef T value_type;
typedef T& reference;
typedef T* pointer;
typedef ItT iterator_type;
iterator_type& operator=(const iterator_type &rhs)
{
p = static_cast<const iterator_impl_t&>(rhs).p;
return dynamic_cast<iterator_type&>(*this);
}
iterator_type& operator++()
{
++p;
return dynamic_cast<iterator_type&>(*this);
}
reference operator*() const
{
return *p;
}
private:
pointer p;
};
template <typename T, typename ItT>
struct iinput_iterator_t : public virtual iiterator_t<T, ItT> {
typedef T value_type;
typedef T& reference;
typedef T* pointer;
typedef ItT iterator_type;
virtual iterator_type operator++(int) = 0;
};
template <typename T, typename ItT>
struct input_iterator_impl_t :
public virtual iinput_iterator_t<T, ItT>,
public virtual iterator_impl_t<T, ItT>
{
typedef T value_type;
typedef T& reference;
typedef T* pointer;
typedef ItT iterator_type;
iterator_type operator++(int)
{
iterator_type result(dynamic_cast<const iterator_type &>(*this));
++dynamic_cast<iterator_impl_t<T, ItT> &>(*this);
return result;
}
};
template <typename T>
struct iterator :
public virtual iterator_impl_t<T, iterator<T> >
{
};
template <typename T>
struct input_iterator :
public virtual input_iterator_impl_t<T, input_iterator<T>>
{
};
int main(int , char** )
{
iterator<int> i;
iterator<int> i2 = ++i;
input_iterator<int> inpi;
input_iterator<int> inpi2 = inpi++;
return 0;
}
迭代器类别只不过是充当标签的空结构。
完成迭代器类的功能实现后,将其信息(如它属于哪个类别)添加到std::iterator_traits
专用化中。 下面是一个示例:
namespace std {
template <typename T>
struct iterator_traits<my_iota_iterator<T>> {
using value_type = T;
using difference_type = T;
using pointer = T const*;
using reference = T const&;
using iterator_category = std::random_access_iterator_tag; // !!
} /*struct iterator_traits*/;
} /*namespace std*/;
还可以选择将这些类型别名直接放在迭代器类本身中。 无论如何,算法现在可以专注于iterator_category
类型,并为特定类别实现特定版本。
相关文章:
- 在文件上实现迭代器
- C++迭代器:实现迭代器类时出错
- 我可以在没有堆栈的情况下在二叉搜索树中实现迭代器吗?
- 如何实现常量迭代器?
- 如何为我的容器实现随机访问迭代器?
- 比较迭代器会使程序崩溃,而不会在自定义气泡排序实现中出现错误
- 如何正确实现自动迭代器
- 在 C++17 中实现迭代器和const_iterator的正确方法是什么?
- 为自定义数组实现迭代器
- 实现迭代器,以许多向量的组合
- 我可以在戒指中实现迭代器end()吗?
- 实现迭代器通用方法的正确方式
- 自定义列表实现迭代器无法访问最后一个元素 (c++)
- c++为自定义矩阵类实现迭代器
- 如何实现迭代器类型的运算符>?
- 在实现迭代器和const_iterator类时避免代码重复的最佳实践
- 即使不需要也要实现迭代器?c++
- 实现++迭代器和迭代器++的混淆
- 尝试在没有显式容器的情况下实现迭代器
- 如何在c++中的派生类中实现迭代器