<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title><code>views::(take|drop)_exactly</code></title>
  <style type="text/css">
    body {
      font-variant-ligatures: none;
    }

    p {
      text-align: justify
    }

    li {
      text-align: justify
    }

    blockquote.note,
    div.note {
      background-color: #E0E0E0;
      padding-left: 15px;
      padding-right: 15px;
      padding-top: 1px;
      padding-bottom: 1px;
    }

    p code {
      color: navy
    }

    ins p code {
      color: #00A000
    }

    p ins code {
      color: #00A000
    }

    p del code {
      color: #A00000
    }

    ins {
      color: #00A000
    }

    del {
      color: #A00000
    }

    table#boilerplate {
      border: 0
    }

    table#boilerplate td {
      padding-left: 2em
    }

    table.bordered,
    table.bordered th,
    table.bordered td {
      border: 1px solid;
      text-align: center;
    }

    ins.block {
      color: #00A000;
      text-decoration: none
    }

    del.block {
      color: #A00000;
      text-decoration: none
    }

    #hidedel:checked~* del,
    #hidedel:checked~* del * {
      display: none;
      visibility: hidden
    }
  </style>
</head>

<body data-new-gr-c-s-check-loaded="14.1043.0" data-gr-ext-installed="">
  <table id="boilerplate">
    <tbody>
      <tr>
        <td>Document number</td>
        <td>P3230R0</td>
      </tr>
      <tr>
        <td>Date</td>
        <td>2024-04-05</td>
      </tr>
      <tr>
        <td>Audience</td>
        <td>LEWG, SG9 (Ranges)</td>
      </tr>
      <tr>
        <td>Reply-to</td>
        <td>Hewill Kang &lt;hewillk@gmail.com&gt;</td>
      </tr>
    </tbody>
  </table>
  <hr>
  <h1><code>views::(take|drop)_exactly</code></h1>
  <ul>
    <li>
      <ul>
        <li>Abstract</li>
        <li>Revision history</li>
        <li>Discussion</li>
        <li>Design</li>
        <li>Implementation experience</li>
        <li>Proposed change</li>
        <li>References</li>
      </ul>
    </li>
  </ul>
  <a name="Abstract"></a>
  <h2>Abstract</h2>
  <p>
    This paper proposes Tier 1 adaptors in <a
      href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2760r1.html">P2760</a>:
    <code>views::drop_exactly</code> and <code>views::take_exactly</code>, which are cousins of <code>drop</code>
    and <code>take</code>, to improve the C++26
    ranges facilities.
  </p>
  <a name="Revision history"></a>
  <h2>Revision history</h2>
  <p>
  <h3>R0</h3>
  <p>Initial revision.</p>
  </p>
  </ol>
  </p>
  <a name="Discussion"></a>
  <h2>Discussion</h2>
  <p>
    <code>drop_exactly</code> and <code>take_exactly</code> are very similar to <code>drop</code> and <code>take</code>,
    the only difference is that the former requires that <code><i>N</i></code> must not be greater than the number of
    elements in the original range; otherwise, it will be NB, which is exactly the "exactly" part.
  </p>
  <p>
    Since there is no bounds check, <code>views::<i>meow</i>_exactly</code> is more efficient than
    <code>views::<i>meow</i></code> for situations where the user already knows that there are enough elements
    in the range.
  </p>
  </ol>
  <a name="Design"></a>
  <h2>Design</h2>
  <p>
  <h3>
    Should we introduce <code>drop_exactly_view</code>/<code>take_exactly_view</code> classes?
  </h3>
  <p>
    Although both can achieve similar effects with existing utilities, e.g.
    <code>take_exactly(r, N)</code> is somewhat equivalent to <code>views::counted(ranges::begin(r), N)</code>, and
    <code>drop_exactly</code> is somewhat equivalent to
    <code>subrange(ranges::next(std::ranges::begin(r), N), ranges::end(r))</code>, these are not fully replaceable
    due to certain limitations.
    The main issue is that both need to apply <code>ranges::begin</code> to extract the iterator of the origin range,
    which
    may be ill-formed when taking rvalue ranges,
    not to mention that <code>drop_exactly_view</code> also needs to cache the result to meet the time complexity
    requiring by the <code>range</code> concept.
  </p>
  <p>
    Since we've already assumed that the range is large enough, out-of-bounds cases are ignored in the implementation,
    which means that <code><i>meow</i>_exactly_view</code> is just a
    reduced version of <code><i>meow</i>_view</code>. So introducing these classes doesn't bring much complexity to the
    standard.
  </p>
  <h3>
    Should we specialized for return types?</h3>
  <p>Currently, both <code>take</code> and <code>drop</code>
    have optimized the return type, that is, when it takes an object of range type <code>empty_view</code>,
    <code>span</code>, <code>string_view</code>, <code>subrange</code>, <code>iota_view</code> and
    <code>repeat_view</code>, it will return an object of the same type to reduce template instantiation. There is no
    reason not to apply similar optimizations to <code>take_exactly</code> and <code>drop_exactly</code>.
  </p>
  <p>However, it should be noted that compared to the former, since we no longer care whether the specialized type
    models
    <code>sized_range</code>, <code>views::<i>meow</i>_exactly</code> applied to the infinite range may downgrade it to
    a
    finite
    range.
    For example, <code>views::iota(0) | views::take_exactly(5)</code> will produce
    <code>views::iota(0, 5)</code>, and <code>views::iota(0) | views::drop_exactly(5)</code> will produce
    <code>views::iota(5)</code>, this applies to <code>subrange&lt;int*, unreachable_sentinel_t&gt;</code> as well.
  </p>
  <h3>Other <i>exactly</i> family?</h3>
  Although <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2760r1.html">P2760</a> only mentions
  <code>take_exactly</code> and <code>drop_exactly</code>, it is natural to think
  whether we need <code>slice_exactly</code>, <code>take_last_exactly</code> and <code>drop_last_exactly</code>, etc.
  Considering the bandwidth of LEWG, this paper does not intend to introduce these potentially useful utilities.</p>
  <a name="Implementation experience"></a>
  <h2>Implementation experience</h2>
  <p>The author implemented <code>views::(take|drop)_exactly</code> based on libstdc++, see <a
      href="https://godbolt.org/z/r9YW4KG6W">here</a>.</p>
  <a name="Proposed-change"></a>
  <h2>Proposed change</h2>
  <p>This wording is relative to <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4971.pdf">N4971</a>.
  </p>
  </div>
  <div>
    <ol>
      <ol>
        <li>
          <p>Add a new feature-test macro to 17.3.2 <a href="https://eel.is/c++draft/version.syn">[version.syn]</a>:
          </p>
          <blockquote>
            <pre><ins>#define __cpp_lib_ranges_take_exactly 2024XXL // <i>freestanding, also in</i> &lt;ranges&gt;</ins></pre>
            <pre><ins>#define __cpp_lib_ranges_drop_exactly 2024XXL // <i>freestanding, also in</i> &lt;ranges&gt;</ins></pre>
          </blockquote>
        </li>

        <li>
          <p>Modify 26.2 <a href="https://eel.is/c++draft/ranges.syn">[ranges.syn]</a>, Header <tt>&lt;ranges&gt;</tt>
            synopsis, as indicated:</p>

          <blockquote>
            <pre>
#include &lt;compare&gt;              // <i>see <a href="https://eel.is/c++draft/compare.syn">[compare.syn]</a></i>
#include &lt;initializer_list&gt;     // <i>see <a href="https://eel.is/c++draft/initializer.list.syn">[initializer.list.syn]</a></i>
#include &lt;iterator&gt;             // <i>see <a href="https://eel.is/c++draft/iterator.synopsis">[iterator.synopsis]</a></i>

namespace std::ranges {
  [&hellip;]
  namespace views { inline constexpr <i>unspecified</i> take = <i>unspecified</i>; }              // <i>freestanding</i>

<ins>  // <i>[range.take.exactly]</a>, take exactly view</i>
  template&lt;view&gt; class take_exactly_view;                                           // <i>freestanding</i>

  template&lt;class T&gt;
    constexpr bool enable_borrowed_range&lt;take_exactly_view&lt;T&gt;&gt; =                    // <i>freestanding</i>
      enable_borrowed_range&lt;T&gt;;

  namespace views { inline constexpr <i>unspecified</i> take_exactly = <i>unspecified</i>; }      // <i>freestanding</i></ins>
  [&hellip;]
  namespace views { inline constexpr <i>unspecified</i> drop = <i>unspecified</i>; }              // <i>freestanding</i>

<ins>  // <i>[range.drop.exactly]</a>, drop exactly view</i>
  template&lt;view V&gt; class drop_exactly_view;                                         // <i>freestanding</i>

  template&lt;class T&gt;
    constexpr bool enable_borrowed_range&lt;drop_exactly_view&lt;T&gt;&gt; =                    // <i>freestanding</i>
      enable_borrowed_range&lt;T&gt;;

  namespace views { inline constexpr <i>unspecified</i> drop_exactly = <i>unspecified</i>; }      // <i>freestanding</i></ins>
  [&hellip;]
}
        </pre>
          </blockquote>
        </li>
        <li>
          <p>Add <b>26.7.? Take exactly view [range.take.exactly]</b></a> after 26.7.10 <a
              href="https://eel.is/c++draft/range.take">[range.take]</a> as indicated:</p>
          <p>[26.7.?.1] Overview [range.take.exactly.overview]</p>
          <p>
            -1- <code>take_exactly_view</code> produces a view of the first <code><i>N</i></code> elements from another
            view.
            The behavior is undefined if the adapted view contains fewer than <code><i>N</i></code> elements.
          </p>
          <p>
            -2- The name <code>views::take_exactly</code> denotes a range adaptor object (26.7.2 <a
              href="https://eel.is/c++draft/range.adaptor.object">[range.adaptor.object]</a>).
            Let <code>E</code> and <code>F</code> be expressions, let <code>T</code> be
            <code>remove_cvref_t&lt;decltype((E))&gt;</code>,
            and let <code>D</code> be <code>range_difference_t&lt;decltype((E))&gt;</code>.
            If <code>decltype((F))</code> does not model <code>convertible_to&lt;D&gt;</code>,
            <code>views::take_exactly(E, F)</code>
            is ill-formed. Otherwise, the expression <code>views::take_exactly(E, F)</code> is expression-equivalent to:
          </p>
          <ol style="list-style-type: none">
            <li>
              <p>(2.1) &mdash; if <code>T</code> is a specialization of <code>empty_view</code> (26.6.2.2 <a
                  href="https://eel.is/c++draft/range.empty.view">[range.empty.view]</a>),
                then <code>((void)F, <i>decay-copy</i>(E))</code>, except that the evaluations of <code>E</code>
                and <code>F</code> are indeterminately sequenced.
              </p>
            </li>
            <li>
              <p>(2.2) &mdash; Otherwise, if <code>T</code> models <code>random_access_range</code>
                and is a specialization of <code>span</code> (24.7.2.2 <a
                  href="https://eel.is/c++draft/views.span">[views.span]</a>),
                <code>basic_string_view</code> (23.3 <a href="https://eel.is/c++draft/string.view">[string.view]</a>),
                or
                <code>ranges::subrange</code>
                (26.5.4 <a href="https://eel.is/c++draft/range.subrange">[range.subrange]</a>), then <code>U(ranges::begin(E), ranges::begin(E) + 
                  static_cast&lt;D&gt;(F))</code>, except that <code>E</code> is evaluated only once,
                where <code>U</code> is a type determined as follows:
              </p>
              <ol style="list-style-type: none">
                <li>
                  <p>(2.2.1) &mdash; if <code>T</code> is a specialization of <code>span</code>, then <code>U</code> is
                    <code>span&lt;typename T::element_type&gt;</code>;
                  </p>
                </li>
                <li>
                  <p>(2.2.2) &mdash; otherwise, if <code>T</code> is a specialization of <code>basic_string_view</code>,
                    then
                    <code>U</code> is <code>T</code>;
                  </p>
                </li>
                <li>
                  <p>(2.2.3) &mdash; otherwise, <code>T</code> is a specialization of <code>subrange</code>,
                    and <code>U</code> is <code>subrange&lt;iterator_t&lt;T&gt;&gt;</code>;</p>
                </li>
              </ol>
            </li>
            <li>
              <p>(2.3) &mdash; otherwise, if <code>T</code> is a specialization of <code>iota_view</code>
                (26.6.4.2 <a href="https://eel.is/c++draft/range.iota.view">[range.iota.view]</a>) that models
                <code>random_access_range</code>, then
                <code>iota_view(*ranges::begin(E), *(ranges::begin(E) + static_cast&lt;D&gt;(F)))</code>,
                except that <code>E</code> is evaluated only once.
              </p>
            </li>
            <li>
              <p>(2.4) &mdash; Otherwise, if <code>T</code> is a specialization of <code>repeat_view</code>
                (26.6.5.2 <a href="https://eel.is/c++draft/range.repeat.view">[range.repeat.view]</a>), then
                <code>views::repeat(*E.<i>value_</i>, static_cast&lt;D&gt;(F))</code>.
              </p>
            </li>
            <li>
              <p>(2.5) &mdash; Otherwise, <code>take_exactly_view(E, F)</code>.</p>
            </li>
          </ol>

          <p>-3- [<i>Example 1</i>:</p>
          <pre>
  auto ints = views::iota(0) | views::take_exactly(10);
  for (auto i : ints | views::reverse) {
    cout &lt;&lt; i &lt;&lt; ' ';  // <i>prints</i> 9 8 7 6 5 4 3 2 1 0
  }</pre>
          — <i>end example]</i>
          <p>[26.7.?.2] Class template <code>take_exactly_view</code> [range.take.exactly.view]</p>
          <pre>
  namespace std::ranges {
    template&lt;view V&gt;
    class take_exactly_view : public view_interface&lt;take_exactly_view&lt;V&gt;&gt; {
    private:
      V <i>base_</i> = V();                                      // <i>exposition only</i>
      range_difference_t&lt;V&gt; <i>count_</i> = 0;                   // <i>exposition only</i>

    public:
      take_exactly_view() requires default_initializable&lt;V&gt; = default;
      constexpr explicit take_exactly_view(V base, range_difference_t&lt;V&gt; count);
  
      constexpr V base() const & requires copy_constructible&lt;V&gt; { return <i>base_</i>; }
      constexpr V base() && { return std::move(<i>base_</i>); }
  
      constexpr auto begin() requires (!<i>simple-view</i>&lt;V&gt;) {
        if constexpr (random_access_range&lt;V&gt;)
          return ranges::begin(<i>base_</i>);
        else
          return counted_iterator(ranges::begin(<i>base_</i>), <i>count_</i>);
      }
  
      constexpr auto begin() const requires range&lt;const V&gt; {
        if constexpr (random_access_range&lt;const V&gt;)
          return ranges::begin(<i>base_</i>);
        else
          return counted_iterator(ranges::begin(<i>base_</i>), <i>count_</i>);
      }
  
      constexpr auto end() requires (!<i>simple-view</i>&lt;V&gt;) {
        if constexpr (random_access_range&lt;V&gt;)
          return ranges::begin(<i>base_</i>) + <i>count_</i>;
        else
          return default_sentinel;
      }
  
      constexpr auto end() const requires range&lt;const V&gt; {
        if constexpr (random_access_range&lt;const V&gt;)
          return ranges::begin(<i>base_</i>) + range_difference_t&lt;const V&gt;(<i>count_</i>);
        else
          return default_sentinel;
      }
  
      constexpr auto size() const noexcept { return <i>to-unsigned-like</i>(<i>count_</i>); }
    };
  
    template&lt;class R&gt;
      take_exactly_view(R&amp;&amp;, range_difference_t&lt;R&gt;)
        -&gt; take_exactly_view&lt;views::all_t&lt;R&gt;&gt;;
  }
</pre>
          <pre>constexpr explicit take_exactly_view(V base, range_difference_t&lt;V&gt; count);</pre>
          <blockquote>
            <p>-1- <i>Preconditions</i>: <code>count &lt;= ranges::distance(base)</code> is <code>true</code>.
            </p>
            <p>-2- <i>Effects</i>: Initializes <code><i>base_</i></code> with <code>std::move(base)</code> and
              <code><i>count_</i></code> with <code>count</code>.
            </p>
          </blockquote>
        <li>
          <p>Add <b>26.7.? Drop exactly view [range.drop.exactly]</b></a> after 26.7.12 <a
              href="https://eel.is/c++draft/range.drop">[range.drop]</a> as indicated:</p>
          <p>[26.7.?.1] Overview [range.drop.exactly.overview]</p>
          <p>
            -1- <code>drop_exactly_view</code> produces a view excluding the first <code><i>N</i></code> elements from
            another view.
            The behavior is undefined if the adapted view contains fewer than <code><i>N</i></code> elements.
          </p>
          <p>
            -2- The name <code>views::drop_exactly</code> denotes a range adaptor object (26.7.2 <a
              href="https://eel.is/c++draft/range.adaptor.object">[range.adaptor.object]</a>).
            Let <code>E</code> and <code>F</code> be expressions, let <code>T</code> be
            <code>remove_cvref_t&lt;decltype((E))&gt;</code>,
            and let <code>D</code> be <code>range_difference_t&lt;decltype((E))&gt;</code>.
            If <code>decltype((F))</code> does not model <code>convertible_to&lt;D&gt;</code>,
            <code>views::drop_exactly(E, F)</code>
            is ill-formed. Otherwise, the expression <code>views::drop_exactly(E, F)</code> is expression-equivalent to:
          </p>
          <ol style="list-style-type: none">
            <li>
              <p>(2.1) &mdash; if <code>T</code> is a specialization of <code>empty_view</code> (26.6.2.2 <a
                  href="https://eel.is/c++draft/range.empty.view">[range.empty.view]</a>),
                then <code>((void)F, <i>decay-copy</i>(E))</code>, except that the evaluations of <code>E</code>
                and <code>F</code> are indeterminately sequenced.
              </p>
            </li>
            <li>
              <p>(2.2) &mdash; Otherwise, if <code>T</code> models <code>random_access_range</code>
                and is
              </p>
              <ol style="list-style-type: none">
                <li>
                  <p>(2.2.1) &mdash; a specialization of <code>span</code> (24.7.2.2 <a
                      href="https://eel.is/c++draft/views.span">[views.span]</a>),</p>
                </li>
                <li>
                  <p>(2.2.2) &mdash; a specialization of <code>basic_string_view</code> (23.3 <a
                      href="https://eel.is/c++draft/string.view">[string.view]</a>), </p>
                </li>
                <li>
                  <p>(2.2.3) &mdash; a specialization of <code>iota_view</code> (26.6.4.2 <a
                      href="https://eel.is/c++draft/range.iota.view">[range.iota.view]</a>), or</p>
                </li>
                <li>
                  <p>(2.2.4) &mdash; a specialization of <code>subrange</code> (26.5.4 <a
                      href="https://eel.is/c++draft/range.subrange">[range.subrange]</a>)
                    where <code>T::<i>StoreSize</i></code> is <code>false</code>,</p>
                </li>
              </ol>
              <p>then <code>U(ranges::begin(E) + static_cast&lt;D&gt;(F), ranges::end(E))</code>,
                except that <code>E</code> is evaluated only once, where <code>U</code> is <code>span&lt;typename
                  T::element_type&gt;</code>
                if <code>T</code> is a specialization of <code>span</code> and <code>T</code> otherwise.
              </p>
            </li>
            <li>
              <p>(2.3) &mdash; Otherwise, if <code>T</code> is a specialization of <code>subrange</code>
                (26.5.4 <a href="https://eel.is/c++draft/range.subrange">[range.subrange]</a>) that models
                <code>random_access_range</code> and <code>sized_range</code>, then
                <code>T(ranges::begin(E) + static_cast&lt;D&gt;(F), ranges::end(E),
                  <i>to-unsigned-like</i>(ranges::distance(E) - static_cast&lt;D&gt;(F)))</code>,
                except that <code>E</code> and <code>F</code> are each evaluated only once.
              </p>
            </li>
            <li>
              <p>(2.4) &mdash; Otherwise, if <code>T</code> is a specialization of <code>repeat_view</code> (26.6.5.2 <a
                  href="https://eel.is/c++draft/range.repeat.view">[range.repeat.view]</a>):
              </p>
              <ol style="list-style-type: none">
                <li>
                  <p>(2.4.1) &mdash; if <code>T</code> models <code>sized_range</code>, then
                  <pre>  views::repeat(*E.<i>value_</i>, ranges::distance(E) - static_cast&lt;D&gt;(F))</pre>
                  except that <code>E</code> is evaluated only once;</p>
                </li>
                <li>
                  <p>(2.4.2) &mdash; otherwise, <code>((void)F, <i>decay-copy</i>(E))</code>, except that the
                    evaluations of
                    <code>E</code> and <code>F</code> are indeterminately sequenced.
                  </p>
                </li>
              </ol>
            </li>
            <li>
              <p>(2.5) &mdash; Otherwise, <code>drop_exactly_view(E, F)</code>.
              </p>
            </li>
            </p>
            <p>-3- [<i>Example 1</i>:</p>
            <pre>
  vector&lt;int&gt; v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  for (int i : is | views::drop_exactly(6) | views::take_exactly(3)) {
    cout &lt;&lt; i &lt;&lt; ' '; // <i>prints</i> 6 7 8
  }</pre>
            — <i>end example]</i>
            <p>[26.7.?.2] Class template <code>drop_exactly_view</code> [range.drop.exactly.view]</p>
            <pre>
    namespace std::ranges {
      template&lt;view V&gt;
      class drop_exactly_view : public view_interface&lt;drop_exactly_view&lt;V&gt;&gt; {
      public:
        drop_exactly_view() requires default_initializable&lt;V&gt; = default;
        constexpr explicit drop_exactly_view(V base, range_difference_t&lt;V&gt; count);
    
        constexpr V base() const & requires copy_constructible&lt;V&gt; { return <i>base_</i>; }
        constexpr V base() && { return std::move(<i>base_</i>); }
    
        constexpr auto begin()
          requires (!(<i>simple-view</i>&lt;V&gt; &amp;&amp; random_access_range&lt;const V&gt;));
        constexpr auto begin() const requires random_access_range&lt;const V&gt;;
    
        constexpr auto end() requires (!<i>simple-view</i>&lt;V&gt;)
        { return ranges::end(<i>base_</i>); }
    
        constexpr auto end() const requires range&lt;const V&gt;
        { return ranges::end(<i>base_</i>); }
    
        constexpr auto size() requires sized_range&lt;V&gt; {
          return ranges::size(<i>base_</i>) - static_cast&lt;range_size_t&lt;V&gt;&gt;(<i>count_</i>);
        }
    
        constexpr auto size() const requires sized_range&lt;const V&gt; {
          return ranges::size(<i>base_</i>) - static_cast&lt;range_size_t&lt;const V&gt;&gt;(<i>count_</i>);
        }
  
      private:
        V <i>base_</i> = V();                                      // <i>exposition only</i>
        range_difference_t&lt;V&gt; <i>count_</i> = 0;                   // <i>exposition only</i>
      };
    
      template&lt;class R&gt;
        drop_exactly_view(R&amp;&amp;, range_difference_t&lt;R&gt;)
          -&gt; drop_exactly_view&lt;views::all_t&lt;R&gt;&gt;;
    }
  </pre>
            <pre>constexpr explicit drop_exactly_view(V base, range_difference_t&lt;V&gt; count);</pre>
            <blockquote>
              <p>-1- <i>Preconditions</i>: <code>count &lt;= ranges::distance(base)</code> is <code>true</code>.
              </p>
              <p>-2- <i>Effects</i>: Initializes <code><i>base_</i></code> with <code>std::move(base)</code> and
                <code><i>count_</i></code> with <code>count</code>.
              </p>
            </blockquote>
            <pre>constexpr auto begin() requires (!(<i>simple-view</i>&lt;V&gt; &amp;&amp; random_access_range&lt;const V&gt;));
constexpr auto begin() const requires random_access_range&lt;const V&gt;</pre>
            <blockquote>
              <p>
                -3- <i>Returns</i>: <code>ranges::next(ranges::begin(<i>base_</i>), <i>count_</i>)</code>.
              </p>
              <p>
                -4- <i>Remarks</i>:
                In order to provide the amortized constant-time complexity required by the <code>range</code> concept
                when <code>drop_exactly_view</code> models <code>forward_range</code>, the first overload caches the
                result within the
                <code>drop_exactly_view</code> for use on subsequent calls.
              </p>
              [<i>Note 1</i>: Without this, applying a <code>reverse_view</code> over a <code>drop_exactly_view</code>
              would have
              quadratic iteration complexity. &mdash; <i>end note</i>]
              </p>
            </blockquote>
            <blockquote>
            </blockquote>
            </blockquote>
            </blockquote>
            </blockquote>
        </li>
      </ol>
    </ol>
  </div>
  <a name="References"></a>
  <h2>References</h2>
  <dd>
  <dt id="biblio-p2760">[P2760R1]
  <dd>Barry Revzin. A Plan for C++26 Ranges. URL: <a
      href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2760r1.html">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2760r1.html</a>
</body>

</html>