In the old way of looking at the world, forward iterators need to return real references. Since dereferencing iota_view's iterators returns by value, it cannot be a C++17 forward iterator. (It can, however, be a C++20 forward_iterator.) However, iota_view's iterator has an iterator_category that (sometimes) falsely claims that it is forward or better (depending on the properties of the weakly_incrementable type it wraps).
Proposed Resolution
Change the synopsis of iota_view::iterator in [range.iota.iterator] as follows:
namespace std::ranges {
template<class W, class Bound>
struct iota_view<W, Bound>::iterator {
private:
W value_ = W(); // exposition only
public:
- using iterator_category = see below ;
+ using iterator_concept = see below ;
+ using iterator_category = input_iterator_tag;
using value_type = W;
Change [range.iota.iterator]/p1 as follows:
iterator::iterator_categoryconcept is defined as follows:
If W models advanceable, then iterator_categoryconcept is random_access_iterator_tag.
Otherwise, if W models decrementable, then iterator_categoryconcept is bidirectional_iterator_tag.
Otherwise, if W models incrementable, then iterator_categoryconcept is forward_iterator_tag.
Otherwise, iterator_categoryconcept is input_iterator_tag.
In the old way of looking at the world, forward iterators need to return real references. Since dereferencing
iota_view
's iterators returns by value, it cannot be a C++17 forward iterator. (It can, however, be a C++20forward_iterator
.) However,iota_view
's iterator has aniterator_category
that (sometimes) falsely claims that it is forward or better (depending on the properties of theweakly_incrementable
type it wraps).Proposed Resolution
Change the synopsis of
iota_view::iterator
in [range.iota.iterator] as follows:Change [range.iota.iterator]/p1 as follows: