4210. Issue with cache_latest_view::iterator's reference type

Section: 25.7.34.3 [range.cache.latest.iterator] Status: New Submitter: Hewill Kang Opened: 2025-02-09 Last modified: 2025-02-09

Priority: Not Prioritized

View all issues with New status.

Discussion:

cache_latest_view::iterator can be roughly regarded as an iterator that transforms the original iterator's reference, because its reference is always an lvalue which is range_reference_t<V>&, even if the original iterator returns an rvalue.

In this case, it seems a bit odd to still specialize iter_move and return the rvalue reference type of the original iterator, because the original reference has changed, so the former may not form a valid common reference with the original rvalue reference.

That is, in some rare cases even if the cache_latest_view can be legally constructed, it may not be an input_range as indirectly_readable is not satisfied.

A contrived example could be:

struct I {
  using value_type = int;
  using difference_type = int;

  struct move_only_ref {
    move_only_ref(const int&);
    move_only_ref(move_only_ref&&) = default;
  };

  move_only_ref operator*() const;
  I& operator++();
  void operator++(int);
};

using R = ranges::cache_latest_view<ranges::subrange<I, unreachable_sentinel_t>>; // ok

static_assert(input_iterator<I>);
static_assert(ranges::input_range<R>); // failed

It's unclear whether we should change the reference type to range_reference_t<V>&& to preserve the original ref-qualifiers as much as possible (I don't see any discussion of this option in the original paper), or not provide a specialized iter_move, since it's intuitive to have the default iter_move return an rvalue when it always returns an lvalue.

Proposed resolution: