我做了一个集合,我想为它提供一个stl风格的随机访问迭代器。我正在寻找迭代器的示例实现,但我没有找到任何。我知道需要对[]和*操作符进行const重载。“stl风格”的迭代器的要求是什么?还有哪些需要避免的陷阱(如果有的话)?

附加上下文:这是一个库,除非真的需要,否则我不想对它引入任何依赖。我编写了自己的集合,以便能够使用相同的编译器在c++ 03和c++ 11之间提供二进制兼容性(因此没有可能会损坏的STL)。


当前回答

托马斯·贝克尔在这里写了一篇关于这个主题的有用文章。

还有一种(也许更简单)的方法出现在前面的SO:如何正确地实现自定义迭代器和const_iterators?

其他回答

Boost中的iterator_facade文档。Iterator提供了一个关于为链表实现迭代器的很好的教程。您是否可以将其作为在容器上构建随机访问迭代器的起点?

如果没有其他方法,可以查看iterator_facade提供的成员函数和类型定义,并将其作为构建自己的成员函数和类型定义的起点。

托马斯·贝克尔在这里写了一篇关于这个主题的有用文章。

还有一种(也许更简单)的方法出现在前面的SO:如何正确地实现自定义迭代器和const_iterators?

由于不同的原因(部分是教育,部分是限制),我和你在同一条船上。我必须重写标准库的所有容器,并且容器必须符合标准。这意味着,如果我用stl版本替换我的容器,代码将工作相同。这也意味着我必须重写迭代器。

总之,我看了EASTL。除了在使用stl容器或在本科课程中学习了大量关于容器的知识之外。主要原因是EASTL比stl更具可读性(我发现这只是因为缺少所有的宏和直接的编码风格)。里面有一些讨厌的东西(比如异常的#ifdefs),但没有什么能让你不知所措。

正如其他人提到的,查看cplusplus.com关于迭代器和容器的参考。

首先,您可以在这里找到各个迭代器类型需要支持的各种操作的列表。

接下来,当你创建了你的迭代器类时,你需要为std::iterator_traits特化并提供一些必要的类型defs(如iterator_category或value_type),或者从std::iterator派生它,它为你定义了所需的类型defs,因此可以与默认的std::iterator_traits一起使用。

免责声明:我知道有些人不太喜欢cplusplus.com,但是他们提供了一些非常有用的信息。

现在是一个基于范围的for循环的keys迭代器。

template<typename C>
class keys_it
{
    typename C::const_iterator it_;
public:
    using key_type        = typename C::key_type;
    using pointer         = typename C::key_type*;
    using difference_type = std::ptrdiff_t;

    keys_it(const typename C::const_iterator & it) : it_(it) {}

    keys_it         operator++(int               ) /* postfix */ { return it_++         ; }
    keys_it&        operator++(                  ) /*  prefix */ { ++it_; return *this  ; }
    const key_type& operator* (                  ) const         { return it_->first    ; }
    const key_type& operator->(                  ) const         { return it_->first    ; }
    keys_it         operator+ (difference_type v ) const         { return it_ + v       ; }
    bool            operator==(const keys_it& rhs) const         { return it_ == rhs.it_; }
    bool            operator!=(const keys_it& rhs) const         { return it_ != rhs.it_; }
};

template<typename C>
class keys_impl
{
    const C & c;
public:
    keys_impl(const C & container) : c(container) {}
    const keys_it<C> begin() const { return keys_it<C>(std::begin(c)); }
    const keys_it<C> end  () const { return keys_it<C>(std::end  (c)); }
};

template<typename C>
keys_impl<C> keys(const C & container) { return keys_impl<C>(container); }

用法:

std::map<std::string,int> my_map;
// fill my_map
for (const std::string & k : keys(my_map))
{
    // do things
}

这正是我要找的。但似乎没有人拥有它。

我给你的强迫症编码是额外奖励。

作为练习,编写您自己的值(my_map)