C ++中的简单流迭代器

时间:2016-09-27 16:16:17

标签: c++ c++11

考虑类似Java的流迭代器:

template<class V>
struct Iterator
{
  V& next();
  bool hasNext();
}

template<class V>
struct Iterable
{
    Iterator<V> iterator();
}

如何将它转换为std :: iterator,以便在find,for-loops等中使用它。

我想我需要从InputIterator开始,但我在这里遇到以下问题:

  • 有意义的结束()?
  • 他们什么时候相等()?
  • 距离怎么样?

1 个答案:

答案 0 :(得分:1)

这是可行的,但很痛苦。

你最好做一个基于生成器的迭代器,其后备操作是std::function< optional<T> >。这是一个这样的生成器迭代器的例子:

template<class T>
struct generator_iterator {
  using difference_type=std::ptrdiff_t;
  using value_type=T;
  using pointer=T*;
  using reference=T;
  using iterator_category=std::input_iterator_tag;
  std::optional<T> state;
  std::function< std::optional<T>() > operation;
  // we store the current element in "state" if we have one:
  T operator*() const {
    return *state;
  }
  // to advance, we invoke our operation.  If it returns a nullopt
  // we have reached the end:
  generator_iterator& operator++() {
    state = operation();
    return *this;        
  }
  generator_iterator operator++(int) {
    auto r = *this;
    ++(*this);
    return r;
  }
  // generator iterators are only equal if they are both in the "end" state:
  friend bool operator==( generator_iterator const& lhs, generator_iterator const& rhs ) {
    if (!lhs.state && !rhs.state) return true;
    return false;
  }
  friend bool operator!=( generator_iterator const& lhs, generator_iterator const& rhs ) {
    return !(lhs==rhs);
  }
  // We implicitly construct from a std::function with the right signature:
  generator_iterator( std::function< std::optional<T>() > f ):operation(std::move(f))
  {
    if (operation)
      state = operation();
  }
  // default all special member functions:
  generator_iterator( generator_iterator && ) =default;
  generator_iterator( generator_iterator const& ) =default;
  generator_iterator& operator=( generator_iterator && ) =default;
  generator_iterator& operator=( generator_iterator const& ) =default;
  generator_iterator() =default;
};

使用类似Java的iterface仍然可以完成。

boost中会有一些解决方案可以让您更轻松。但我会把它写在原始的&#34;基于C ++ 17概念,如果你需要它们(或从boost或其他来源中提取),可以向后移植到C ++ 11。

您正在生成输入迭代器,因为这就是类似Java的接口所支持的。

首先,我要写一个帮手。帮助者将拥有optional< Iterator<V> >optional<V>

它会支持++。 ++将推进迭代器并将值读入optional<V>

它会支持一元**将返回可选项中的值。

如果bool is_end()为空,或optional<Iterator<V>>!.hasNext(),则

==会返回true。

当且仅当两个参数.is_end()时,

!=才返回true。 !只会==应用于Iterable<V>

这个助手还不是一个迭代器,但它有大部分关键操作。

然后我们使用this poly_iterator类型擦除任何迭代器。我们上面在帮助器上编写的操作就足够了。

然后我们使用上面的helper伪迭代器编写一个函数,该函数接受range<poly_iterator<T>>并生成上面类型擦除类的range<It>template<class It> struct range { It b; It e; It begin() const { return b; } It end() const { return e; } }; 是一个类似于:

的类
poly_iterator<T>

加上其他实用工具帮助。

如果您选择,可以跳过类型擦除步骤。只需将上面写的帮助器扩充为一个成熟的输入迭代器。 Boost有助手,让这更轻松。让范围返回者返回完整的输入迭代器。我碰巧在另一个答案中躺着var months = ['Jan','Feb','Mar','Apr','May','June','July','Aug','Sept','Oct','Nov','Dec']; ,如果你有一把锤子,问题确实看起来像钉子。

请注意,为了让代码真正像Java一样,我们希望实际拥有指向对象的(智能)指针而不是副本。