range-v3和view_facade,无法建模ForwardRange

4

这个缩小的测试用例(按照用户手册中的示例编写)无法编译。

#include <range/v3/all.hpp>
#include <vector>

using v = std::vector<int>;

class rows : public ranges::view_facade<rows> {
  public:
    rows() = default;
    explicit rows(const v& data) : it_(data.begin()), end_(data.end()) {}

  private:
    friend ranges::range_access;
    v::const_iterator it_;
    v::const_iterator end_;

    const int& read() const {
        return *it_;
    }

    bool equal(ranges::default_sentinel) const {
        return it_ == end_;
    }

    void next() {
        ++it_;
    }
};

int main() {
    v data{10, 20, 30, 40};
    auto rng = rows(data) | ranges::view::unique;
}

由于根据view::unique,我的范围不符合ForwardRange概念,所以编译会因静态断言而失败。

但是,如果我重写我的类来使用显式游标,那么编译将成功。

class rows : public ranges::view_facade<rows> {
  public:
    rows() = default;
    explicit rows(const v& data) : data_{&data} {}

  private:
    friend ranges::range_access;

    const v* data_;

    struct cursor {
        cursor() = default;
        cursor(v::const_iterator iter) : it{iter} {}

        const int& read() const {
            return *it;
        }
        bool equal(const cursor& other) const {
            return it == other.it;
        }
        void next() {
            ++it;
        }

        v::const_iterator it;
    };

    cursor begin_cursor() const {
        return {data_->begin()};
    }
    cursor end_cursor() const {
        return {data_->end()};
    }
};

为什么第一个类不是ForwardRange,而第二个类可以? view_facade<>::(begin|end)_cursor() 默认返回派生类的实例,所以我不明白为什么它不起作用。 我已经添加了一个静态断言来确保 ranges::range_access::single_pass_t 为 false,所以我怀疑问题与 ForwardIterator 概念有关。
1个回答

4
您定义了equal(ranges::default_sentinel) const,但没有定义equal(const rows&),因此您的范围迭代器类型将满足 EqualityComparableWith<ranges::default_sentinel>,但不满足EqualityComparable。前向迭代器(及更强)需要满足EqualityComparable,因此rows满足InputRange,但不满足ForwardRange
建议您定义以下内容:
bool equal(const rows& that) const {
    return it_ == that.it_;
}

同时该程序表现出了您所期望的行为


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接