This code does not compile with range-v3
0.10.0
(or with master
). It does compile with range-v3
0.9.1
.
#include "range/v3/all.hpp"
struct double_it {
using value_type = double;
double x;
double& operator*() { return x; }
const double& operator*() const { return x; }
};
static_assert(ranges::readable<double_it>);
Which version is right ? In master
, a type I
is readable
only if same_as<iter_reference_t<I const>, iter_reference_t<I>>
. I don't understand why the return type of operator*
should be the same as the one of operator* const
.
Note: issue submitted on github here.
Take a look at P1878, which has all the rationale for this late design change. Iterators represent indirections. In C++, const
-ness is shallow, meaning it doesn't follow indirections. Whether you dereference an int*
or an int*const
, the result you get back is the same: int&
. The top-level const
doesn't -- and shouldn't -- matter. Iterators do as the pointers do. They must, because a pointer is a valid model of the iterator concept.
To make this distinction more explicit, in C++20, the readable
concept is called indirectly_readable
.
TL;DR: Don't make the reference type of your iterator depend on the const
-ness of the iterator itself.