我是否可以轻松覆盖 (STL) 迭代器的类别?

Can I easily override an (STL) iterator's category?

本文关键字:迭代器 STL 是否 覆盖      更新时间:2023-10-16

现在,我有一个类可以通过随机访问迭代器满足API要求。 但是,我可以设想一种情况,即实现将发生变化,并且只能提供前向迭代器。

因此,我想限制调用者使用随机访问功能。 我知道我可以编写自己的实现(例如restricted_bar_iterator),但想知道是否有更简单的东西(即需要更少的编码)。

class BAR { ... };
class FOO {
public:
    // Bad...clients may expect 'bar_iterator' to be random access...
    typedef std::vector<BAR>::iterator bar_iterator;
    bar_iterator begin_bar() const;
    bar_iterator end_bar() const;
    // Possible solution here!
    class restricted_bar_iterator :
        public std::iterator< std::forward_iterator_tag, BAR > { ... };
};

void baz()
{
    FOO foo;
    bar_iterator it = foo.begin_bar() + 5; // want a compile time error here!
}

下面是使用Boost Iterator Adaptor的示例。我用int而不是BAR.

#include <boost/iterator/iterator_adaptor.hpp>
#include <vector>
struct iterator :
    public boost::iterator_adaptor<
        iterator,                    // the name of our class, see docs for details
        std::vector<int>::iterator,  // underlying base iterator
        boost::use_default,          // for value type
        boost::forward_traversal_tag // all the boilerplate for this!
    >
{
     // need this to convert from vector::iterator to ours
     explicit iterator(std::vector<int>::iterator i)
      : iterator::iterator_adaptor_(i) {}
};
int main()
{
    std::vector<int> v;
    iterator it(v.begin());
    ++it;    // OK
    it += 1; // ERROR
}

这有效地使用 std::vector<T>::iterator 作为基类,但只允许为前向迭代器定义的操作。缺点是错误消息 - 它们不是很漂亮。

您肯定必须进行一些编码,但您可能能够从底层类型继承以获取大部分功能,只需覆盖您不想使用的操作,方法是将它们定义为在 C++11 中删除或在 C++03 中将它们设为私有且未实现:

class FOO {
    // Bad...clients may expect 'bar_iterator' to be random access...
    typedef std::vector<BAR>::iterator bar_iterator_impl;
public:
    // Possible solution here!
    struct bar_iterator : bar_iterator_impl {
      bar_iterator& operator++() {
        ++static_cast<bar_iterator_impl&>(*this);
        return *this;
      }
      bar_iterator operator++(int) {
        bar_iterator copy(*this);
        ++*this;
        return copy;
      }
      typedef std::forward_iterator_tag iterator_category;    
      typedef std::iterator_traits<bar_iterator_impl>::value_type value_type;
      typedef std::iterator_traits<bar_iterator_impl>::difference_type difference_type;
      typedef std::iterator_traits<bar_iterator_impl>::pointer    pointer;
      typedef std::iterator_traits<bar_iterator_impl>::reference  reference;
    private:
      friend void operator+(bar_iterator const&, long);
      friend void operator+(long, bar_iterator const&);
      friend void operator-(bar_iterator const&, long);
      friend void operator-(long, bar_iterator const&);
    };
    bar_iterator begin_bar() const;
    bar_iterator end_bar() const;
};

但是,这仅在std::vector<BAR>::iterator是类类型时才有效,并且它可以是一个指针,在这种情况下,它不能派生。要实现可移植性,您需要自己定义整个迭代器 API。