在我继承的代码库中,有一个类看起来像是一个迭代器(这不是精确的代码,但逻辑类似)。
template <class T>
struct IteratorLike {
T* next() &; // either return a pointer to a valid value or nullptr
};
使用方式与 Rust 迭代器非常相似:
IteratorLike<...> it = ...;
while(auto* item = it.next()) {
do_something(*item);
}
我该如何将其转换为与C++范围-based for循环、算法或range-v3兼容的格式? 我正在使用C++14(更精确地说是gcc5.5),因此我无法使用与迭代器本身类型不同的哨兵类型。
到目前为止,似乎最简单的方法是在我的包装器中同时存储迭代器和下一个值:
template <class T>
class MyIterator {
private:
IteratorLike<T> m_iter;
T* m_value;
public:
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
using reference = T&;
using iterator_category = std::input_iterator_tag;
reference operator*() const {
assert(m_value && "trying to read past the end of the iterator");
return *m_value;
}
pointer operator->() {
// I’m not sure the assert is needed here
assert(m_value && "trying to read past the end of the iterator");
return m_value;
}
// Prefix increment
MyIterator& operator++() {
m_value = m_iter.next();
return *this;
}
// Postfix increment
MyIterator operator++(int) {
MyIterator tmp = *this;
++(*this);
return tmp;
}
// used by `my_collection.begin()`
explicit MyIterator(IteratorLike<T> iter)
: m_iter{m_iter}
, m_value{this->self.next()}
{}
// missing operator == and operator != as well as the constructor
// used `my_collection.end()
};
然而,我不理解my_collection.end()
应该返回什么(编辑:我刚刚检查了一下,我不能默认初始化m_iter
),也不知道如何编写有意义的比较运算符。
注意:基本上,我正在尝试完全相反于这个例子。
my_collection.end()
。相反,你应该使用空构造的迭代器(类似于流迭代器),在你的!=
运算符中,如果一个迭代器是默认构造的,另一个迭代器返回的指针为 nullptr,则认为两个迭代器相等。 - SergeyAm_iter
?编辑:我刚刚双重检查了,IteratorLike
不是默认可构造的。 - Robinstd::optional<IteratorLike<T>>
(或boost::optional
)。 - Chris Dodd