iota_view::sentinel is not always iota_view's sentinelSection: 25.6.4.2 [range.iota.view] Status: C++23 Submitter: Tim Song Opened: 2021-02-17 Last modified: 2023-11-22
Priority: Not Prioritized
View all other issues in [range.iota.view].
View all issues with C++23 status.
Discussion:
P1739R4 added the following constructor to
iota_view:
constexpr iota_view(iterator first, sentinel last) : iota_view(*first, last.bound_) {}
However, while iota_view's iterator type is always iota_view::iterator, its sentinel type
is not always iota_view::sentinel. First, if Bound is unreachable_sentinel_t, then
the sentinel type is unreachable_sentinel_t too - we don't add an unnecessary level of wrapping
on top. Second, when W and Bound are the same type, iota_view models common_range, and
the sentinel type is the same as the iterator type - that is, iterator, not sentinel.
Presumably the intent is to use the view's actual sentinel type, rather than always use the
sentinel type.
[2021-03-12; Reflector poll]
Set status to Tentatively Ready after five votes in favour during reflector poll.
[2021-06-07 Approved at June 2021 virtual plenary. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4878.
Edit 25.6.4.2 [range.iota.view], as indicated:
namespace std::ranges { // [...] template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t> requires weakly-equality-comparable-with<W, Bound> && semiregular<W> class iota_view : public view_interface<iota_view<W, Bound>> { private: // [range.iota.iterator], class iota_view::iterator struct iterator; // exposition only // [range.iota.sentinel], class iota_view::sentinel struct sentinel; // exposition only W value_ = W(); // exposition only Bound bound_ = Bound(); // exposition only public: iota_view() = default; constexpr explicit iota_view(W value); constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound); constexpr iota_view(iterator first,sentinelsee below last);: iota_view(*first, last.bound_) {}constexpr iterator begin() const; constexpr auto end() const; constexpr iterator end() const requires same_as<W, Bound>; constexpr auto size() const requires see below; }; template<class W, class Bound> requires (!is-integer-like<W> || !is-integer-like<Bound> || (is-signed-integer-like<W> == is-signed-integer-like<Bound>)) iota_view(W, Bound) -> iota_view<W, Bound>; }[...]
constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);-8- Preconditions:
Bounddenotesunreachable_sentinel_torboundis reachable fromvalue. WhenWandBoundmodeltotally_ordered_with, thenbool(value <= bound)is true.-9- Effects: Initializes
value_ withvalueandbound_withbound.constexpr iota_view(iterator first, see below last);-?- Effects: Equivalent to:
(?.1) — If
same_as<W, Bound>istrue,iota_view(first.value_, last.value_).(?.2) — Otherwise, if
Bounddenotesunreachable_sentinel_t,iota_view(first.value_, last).(?.3) — Otherwise,
iota_view(first.value_, last.bound_).-?- Remarks: The type of
lastis:
(?.1) — If
same_as<W, Bound>istrue,iterator.(?.2) — Otherwise, if
Bounddenotesunreachable_sentinel_t,Bound.(?.3) — Otherwise,
sentinel.