考虑类似Java的流迭代器:
template<class V>
struct Iterator
{
V& next();
bool hasNext();
}
template<class V>
struct Iterable
{
Iterator<V> iterator();
}
如何将它转换为std :: iterator,以便在find,for-loops等中使用它。
我想我需要从InputIterator开始,但我在这里遇到以下问题:
答案 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一样,我们希望实际拥有指向对象的(智能)指针而不是副本。