ranges::size
is not required to be valid after a call to ranges::begin
on an input rangeSection: 25.7.10.2 [range.take.view], 25.5.4.2 [range.subrange.ctor] Status: C++20 Submitter: Eric Niebler Opened: 2019-09-10 Last modified: 2021-02-25
Priority: 0
View all other issues in [range.take.view].
View all issues with C++20 status.
Discussion:
On an input (but not forward) range, begin(rng)
is not required to be an equality-preserving
expression (25.4.2 [range.range]/3.3). If the range is also sized, then it is not valid
to call size(rng)
after begin(rng)
(25.4.3 [range.sized]/2.2). In several
places in the ranges clause, this precondition is violated. A trivial re-expression of the effects
clause fixes the problem.
[2019-10-12 Issue Prioritization]
Status to Tentatively Ready and priority to 0 after seven positive votes on the reflector.
Proposed resolution:
This wording is relative to N4830.
Modify 25.7.10.2 [range.take.view], class template take_view
synopsis, as indicated:
namespace std::ranges { template<view V> class take_view : public view_interface<take_view<V>> { private: […] public: […] constexpr auto begin() requires (!simple-view<V>) { if constexpr (sized_range<V>) { if constexpr (random_access_range<V>) return ranges::begin(base_); else { auto sz = size(); return counted_iterator{ranges::begin(base_),size()sz}; } } else return counted_iterator{ranges::begin(base_), count_}; } constexpr auto begin() const requires range<const V> { if constexpr (sized_range<const V>) { if constexpr (random_access_range<const V>) return ranges::begin(base_); else { auto sz = size(); return counted_iterator{ranges::begin(base_),size()sz}; } } else return counted_iterator{ranges::begin(base_), count_}; } […] }; […] }
Modify 25.5.4.2 [range.subrange.ctor] as indicated:
template<not-same-as<subrange> R> requires forwarding-range<R> && convertible_to<iterator_t<R>, I> && convertible_to<sentinel_t<R>, S> constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);-6- Effects: Equivalent to:
(6.1) — If
StoreSize
istrue
,subrange{
.ranges::begin(r), ranges::end(r)r, ranges::size(r)}(6.2) — Otherwise,
subrange{ranges::begin(r), ranges::end(r)}
.