Reputation: 1034
This reduced test case (written following the example in the user manual) does not compile
#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;
}
The compilation fails with a static_assert since, according to view::unique, my range does not model the ForwardRange concept
But if I rewrite my class to use an explicit cursor, the compilation is successful
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()};
}
};
Why the first class is not a ForwardRange and the second instead is ok? view_facade<>::(begin|end)_cursor() by default returns an instance of the derived class, so I don't understand why it does not work.
I've added a static assert to be sure that ranges::range_access::single_pass_t is false, so I suspect that the problem is related with the ForwardIterator concept.
Upvotes: 4
Views: 462
Reputation: 42554
You define equal(ranges::default_sentinel) const
but not equal(const rows&)
, so the iterator type of your range will satisfy EqualityComparableWith<ranges::default_sentinel>
but not EqualityComparable
. Forward iterators (and stronger) are required to satisfy EqualityComparable
, so rows
satisfies InputRange
but not ForwardRange
.
I suggest you define:
bool equal(const rows& that) const {
return it_ == that.it_;
}
and the program behaves as you expect.
Upvotes: 4