c++ - 将next()、hasNext()迭代器接口(interface)转为begin()、end()接口(interface)

标签 c++ iterator c++14

我必须使用无法更改的外部库。除其他外,该库可以通过其内部逻辑对特殊格式的文件进行标记。 tokenizer 提供了一个迭代器接口(interface)来访问 token ,它看起来像下面的简化示例:

class Tokenizer {
public:
    /* ... */
    Token token() const; // returns the current token
    Token next() const; // returns the next token
    bool hasNext() const; // returns 'true' if there are more tokens
    /* ... */
};

我想为呈现的 Tokenizer 实现一个迭代器包装器,它允许使用标准 algorithms library (std::copy_ifstd::count 等)。更具体地说,如果迭代器包装器满足 input iterator 的要求就足够了.

我当前的试用版如下所示:

class TokenIterator {
public:
    using iterator_category = std::input_iterator_tag;
    using value_type = Token;
    using difference_type = std::ptrdiff_t;
    using pointer = const value_type*;
    using reference = const value_type&;

    explicit TokenIterator(Tokenizer& tokenizer) :
            tokenizer(tokenizer) {
    }
    TokenIterator& operator++() {
        tokenizer.next();
        return *this;
    }
    value_type operator*() {
        return tokenizer.token();
    }

private:
    Tokenizer& tokenizer;
};

我被 beginend、相等比较器等函数的实现所困。所以,我的问题是:

  • 如何构造一个 TokenIterator 实例来指示 token 序列的结尾(即 hasNext() == false)以及如何将它与另一个 进行比较code>TokenIterator实例判断是否相同?
  • 如果我从 operator*() 的重载中返回一个值而不是引用,这是一个好方法吗?

最佳答案

首先,我建议仔细查看 http://www.boost.org/doc/libs/1_65_1/libs/iterator/doc/iterator_facade.html

我发现它大大减少了此类代码所需的样板文件数量。

然后,您必须决定希望如何表示已到达“结尾”的迭代器。一种方法是使默认构造的迭代器成为“结束”迭代器。它不包含任何对象,您不能递增或取消引用它。 “开始”迭代器是一个非默认构造的迭代器。它有一个对象,您可以取消引用它。递增此迭代器只需检查 hasNext()。如果为真,则将包含的对象设置为 next()。如果为 false,则清除包含的对象并使此迭代器看起来像默认构造的迭代器。

operator* 按值返回应该没有任何问题。即使您分配给引用,生命周期延长也会保留该值,直到引用超出范围。也就是说,任何假定此类引用在多次迭代后仍然有效的代码都会中断,因此请坚持使用简单的 for (auto val : tokens)for (auto& val : tokens) .

关于c++ - 将next()、hasNext()迭代器接口(interface)转为begin()、end()接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47403058/

相关文章:

c++ - unique_ptr 和 shared_ptr 的重载方法与多态性不明确

c++ - C++ 中运算符 = 的操作数的顺序是怎样的?

c++ - operator== 使用 msvc 编译,但不使用 gcc 和 clang 编译

c++ - 无法将参数的 'double (*)[10]' 转换为 'double*'

c++ - 如何用不同类型的迭代器填充 vector ?

java - 使用迭代器比较数组列表中对象存储的字段

c++ - 什么是已删除函数,为什么只有我传递文件的函数才被视为已删除?

C++ lambdas, "error: expected expression"

c++ - 来自 Rcpp 的 sourceCpp 在规范示例中给出了奇怪的编译错误

loops - 在 Rust 中是否有与 JavaScript 的 forEach 等效的东西?