ericniebler / stl2

LaTeX and Markdown source for the Ranges TS/STL2 and associated proposals
88 stars 8 forks source link

ranges::size is not required to be valid after a call to ranges::begin on an input range #607

Open ericniebler opened 5 years ago

ericniebler commented 5 years ago

Range-v3's debug_input_view::size() asserts if begin() has been called before size(). If that's a legit restriction (is it?) then there is a problem in take_view<V>::begin():

constexpr auto begin() requires (!simple-view <V>) {
  if constexpr (SizedRange<V>) {
    if constexpr (RandomAccessRange<V>)
      return ranges::begin(base_);
    else
      return counted_iterator{ranges::begin(base_), size()}; // <== PROBLEM!
  } else
    return counted_iterator{ranges::begin(base_), count_};
}

If V is an Input, Sized range, then we are calling begin and size in some indeterminate order. That is enough to trigger the assertion in range-v3's debug_input_view.

Proposed Resolution

Change [range.take.view] as follows:

 constexpr auto begin() requires (!simple-view <V>) {
   if constexpr (sized_range<V>) {
     if constexpr (random_access_range<V>)
       return ranges::begin(base_);
-    else
-      return counted_iterator{ranges::begin(base_), size()};
+    else {
+      auto sz = size();
+      return counted_iterator{ranges::begin(base_), 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
-      return counted_iterator{ranges::begin(base_), size()};
+    else {
+      auto sz = size();
+      return counted_iterator{ranges::begin(base_), sz};
+    }
   } else
     return counted_iterator{ranges::begin(base_), count_};
 }

 constexpr auto end() requires (!simple-view <V>) {

Change [range.subrange.ctor]/p6.1 as follows:

If StoreSize is true, subrange{ranges::begin(r), ranges::end(r)r, ranges::size(r)}.

CaseyCarter commented 5 years ago

If that's a legit restriction (is it?)

That's [range.sized]/2.2. debug_input_view strikes again!

CaseyCarter commented 5 years ago

Also affected:

ericniebler commented 5 years ago

Updating range-v3 to be std(-ish) conforming has been really good at exposing these bugs!