<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title>Constexpr for &lt;experimental/ranges/iterator&gt;</title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
  ins {
    color:#009a9a; text-decoration:underline;
  }
  
  del {
    color:red; text-decoration:line-through;
  }
  
  ednote {
    color:blue;
  }
  
  table {
    border-collapse: collapse;
  }
  
  table, th, td {
    border: 1px solid black;
  }
  </style>
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="607">
  <tr>
    <td width="172" align="left" valign="top">Document number:</td>
    <td width="435">
      P0579R1
    </td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Date:</td>
    <td width="435">2017-07-10</td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Project:</td>
    <td width="435">C++ Extensions for Ranges, Library Working Group</td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Reply-to:</td>
    <td width="435">
      Casey Carter &lt;<a href="mailto:Casey@Carter.net">Casey@Carter.net</a>&gt;<br>
    </td>
  </tr>
</table>
<div id="header">
<h1 class="title">Constexpr for &lt;experimental/ranges/iterator&gt;</h1>
</div>
<div id="TOC">
<ul>
<li><a href="#synopsis"><span class="toc-section-number">1</span> Synopsis</a><ul>
<li><a href="#revision-history"><span class="toc-section-number">1.1</span> Revision History</a><ul>
<li><a href="#r1"><span class="toc-section-number">1.1.1</span> R1</a></li>
</ul></li>
</ul></li>
<li><a href="#background"><span class="toc-section-number">2</span> Background</a><ul>
<li><a href="#design-issues-common_iterator"><span class="toc-section-number">2.1</span> Design issues: <code>common_iterator</code></a></li>
<li><a href="#implementation-experience"><span class="toc-section-number">2.2</span> Implementation Experience</a></li>
</ul></li>
<li><a href="#proposed-resolution"><span class="toc-section-number">3</span> Proposed Resolution</a></li>
</ul>
</div>
<h1 id="synopsis"><span class="header-section-number">1</span> Synopsis</h1>
<p>This paper proposes changes to the specification of components declared in the Ranges TS header <code>&lt;experimental/ranges/iterator&gt;</code> to enable them to be used in a constexpr context. These changes resolve Ranges TS issue 256 “Add <code>constexpr</code> to <code>advance</code>, <code>distance</code>, <code>next</code> and <code>prev</code>” (<a href="https://github.com/ericniebler/stl2/issues/256" class="uri">https://github.com/ericniebler/stl2/issues/256</a>), and issue 322 “<code>ranges::exchange</code> should be <code>constexpr</code> and conditionally <code>noexcept</code>” (<a href="https://github.com/ericniebler/stl2/issues/322" class="uri">https://github.com/ericniebler/stl2/issues/322</a>).</p>
<h2 id="revision-history"><span class="header-section-number">1.1</span> Revision History</h2>
<h3 id="r1"><span class="header-section-number">1.1.1</span> R1</h3>
<ul>
<li>Fix formatting SNAFU that caused <code>operator[](difference_type n) const</code> to display as <code>operator const</code> in the class synopses of <code>reverse_iterator</code>, <code>move_iterator</code>, and <code>counted_iterator</code>.</li>
</ul>
<h1 id="background"><span class="header-section-number">2</span> Background</h1>
<p>During review of P0370R2 “Ranges TS Design Updates Omnibus” at Issaquah, LWG directed that functions declared in the header <code>&lt;experimental/ranges/iterator&gt;</code> should be <code>constexpr</code> if they are so in the C++ WP header <code>&lt;iterator&gt;</code>. It was suggested that the new iterator adaptors added in the Ranges TS, <code>counted_iterator</code> and <code>common_iterator</code>, should also be “as <code>constexpr</code> as possible” in the spirit of e.g. <code>reverse_iterator</code> and <code>move_iterator</code>. We’ve enlarged the scope slightly to include some utilities (<code>tagged</code>, <code>dangling</code>, and <code>exchange</code>) to enable the use of the iterator tools to implement constexpr algorithms.</p>
<p>This paper proposes changes to the specification of:</p>
<ul>
<li>the iterator operations <code>advance</code>, <code>next</code>, <code>prev</code>, and <code>distance</code></li>
<li>the iterator adaptors <code>reverse_iterator</code>, <code>move_iterator</code>, <code>counted_iterator</code>, and <code>common_iterator</code></li>
<li>the sentinel adaptor <code>move_sentinel</code></li>
<li>the <code>dangling</code> wrapper class template</li>
<li>class template <code>tagged</code></li>
<li>function template <code>exchange</code></li>
</ul>
<p>to enable those components to be used in the implementation of <code>constexpr</code> algorithms.</p>
<h2 id="design-issues-common_iterator"><span class="header-section-number">2.1</span> Design issues: <code>common_iterator</code></h2>
<p>The design intent of <code>common_iterator&lt;I, S&gt;</code>, for some iterator type <code>I</code> and sentinel type <code>S</code>, is that it be implementable in terms of a C++17 <code>std::variant&lt;I, S&gt;</code>. Unfortunately the limitations of <code>constexpr</code> in C++17 make it impossible to implement the assignment operators of <code>std::variant</code> so as to be generally usable in a <code>constexpr</code> context. Consequently, <code>common_iterator</code>’s assignment operators cannot in general be usable in <code>constexpr</code> context.</p>
<p>Similarly, if either <code>I</code> or <code>S</code> has a nontrivial destructor, <code>common_iterator&lt;I, S&gt;</code> must also have a nontrivial destructor, disqualifying it from being a literal type.</p>
<p>Since an iterator that cannot be assigned is of extremely limited utility, we do not propose to apply <code>constexpr</code> to all member functions of <code>common_iterator</code> at this time; we propose only that the constructors of <code>common_iterator</code> be <code>constexpr</code>.</p>
<h2 id="implementation-experience"><span class="header-section-number">2.2</span> Implementation Experience</h2>
<p>All of the suggested changes have been implemented in CMCSTL2 (<a href="https://github.com/caseycarter/cmcstl2" class="uri">https://github.com/caseycarter/cmcstl2</a>) as a sanity check.</p>
<h1 id="proposed-resolution"><span class="header-section-number">3</span> Proposed Resolution</h1>
<p>Change the synopsis of header <code>&lt;experimental/ranges/utility&gt;</code> in [utility]/2 as follows:</p>
<blockquote>
<p><tt>// 5.2.1, swap:</tt><br />
<tt>namespace {</tt><br />
<tt>  constexpr <i>unspecified</i> swap = <i>unspecified</i>;</tt><br />
<tt>}</tt></p>
<p><tt>// 5.2.2, exchange:</tt><br />
<tt>template &lt;MoveConstructible T, class U=T&gt;</tt><br />
<tt>  requires Assignable&lt;T&amp;, U&gt;()</tt><br />
<tt><ins>constexpr </ins>T exchange(T&amp; obj, U&amp;&amp; new_val)<ins> noexcept(<i>see below</i>)</ins>;</tt></p>
<p><tt>// 5.5.2, struct with named accessors</tt><br />
<tt>template &lt;class T&gt;</tt><br />
<tt>concept bool TagSpecifier() {</tt><br />
<tt>  return <i>see below</i>;</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change the declaration of <code>exchange</code> in [utility.exchange] to agree, and add a new paragraph after paragraph 1:</p>
<blockquote>
<p><tt>template &lt;MoveConstructible T, class U=T&gt;</tt><br />
<tt>  requires Assignable&lt;T&amp;, U&gt;()</tt><br />
<tt><ins>constexpr </ins>T exchange(T&amp; obj, U&amp;&amp; new_val)<ins> noexcept(<i>see below</i>)</ins>;</tt></p>
<p>1 <em>Effects:</em> Equivalent to:</p>
<p><tt>  T old_val = std::move(obj);</tt><br />
<tt>  obj = std::forward&lt;U&gt;(new_val);</tt><br />
<tt>  return old_val;</tt></p>
<ins>
<p>2 <em>Remarks:</em> The expression in the <code>noexcept</code> is equivalent to:</ins></p>
<p><tt>  <ins>is_nothrow_move_constructible&lt;T&gt;::value &amp;&amp;</ins></tt><br />
<tt>  <ins>is_nothrow_assignable&lt;T&amp;, U&gt;::value</ins></tt></p>
</blockquote>
<p>Change the synopsis of class templated <code>tagged</code> in [taggedtup.tagged]/2 as follows:</p>
<blockquote>
<p><tt>template &lt;class Base, TagSpecifier... Tags&gt;</tt><br />
<tt>  requires sizeof...(Tags) &lt;= tuple_size&lt;Base&gt;::value</tt><br />
<tt>struct tagged :</tt><br />
<tt>  Base, <i>TAGGET</i>(tagged&lt;Base, Tags...&gt;, <i>T<sub>i</sub></i>, <i>i</i>)... { // <i>see below</i></tt><br />
<tt>  using Base::Base;</tt><br />
<tt>  tagged() = default;</tt><br />
<tt>  tagged(tagged&amp;&amp;) = default;</tt><br />
<tt>  tagged(const tagged&amp;) = default;</tt><br />
<tt>  tagged&amp; operator=(tagged&amp;&amp;) = default;</tt><br />
<tt>  tagged&amp; operator=(const tagged&amp;) = default;</tt><br />
<tt>  template &lt;class Other&gt;</tt><br />
<tt>    requires Constructible&lt;Base, Other&gt;()</tt><br />
<tt>  <ins>constexpr </ins>tagged(tagged&lt;Other, Tags...&gt;&amp;&amp; that) noexcept(<i>see below</i>);</tt><br />
<tt>  template &lt;class Other&gt;</tt><br />
<tt>    requires Constructible<Base, const Other&amp;>()</tt><br />
<tt>  <ins>constexpr </ins>tagged(const tagged&lt;Other, Tags...&gt;&amp; that);</tt><br />
<tt>  template &lt;class Other&gt;</tt><br />
<tt>    requires Assignable&lt;Base&amp;, Other&gt;()</tt><br />
<tt>  <ins>constexpr </ins>tagged&amp; operator=(tagged&lt;Other, Tags...&gt;&amp;&amp; that) noexcept(<i>see below</i>);</tt><br />
<tt>  template &lt;class Other&gt;</tt><br />
<tt>    requires Assignable&lt;Base&amp;, const Other&amp;&gt;()</tt><br />
<tt>  <ins>constexpr </ins>tagged&amp; operator=(const tagged&lt;Other, Tags...&gt;&amp; that);</tt><br />
<tt>  template &lt;class U&gt;</tt><br />
<tt>    requires Assignable&lt;Base&amp;, U&gt;() &amp;&amp; !Same&lt;decay_t&lt;U&gt;, tagged&gt;()</tt><br />
<tt>  <ins>constexpr </ins>tagged&amp; operator=(U&amp;&amp; u) noexcept(<i>see below</i>);</tt><br />
<tt>  <ins>constexpr </ins>void swap(tagged&amp; that) noexcept(<i>see below</i>)</tt><br />
<tt>    requires Swappable&lt;Base&amp;&gt;();</tt><br />
<tt>  <ins>constexpr </ins>friend void swap(tagged&amp;, tagged&amp;) noexcept(<i>see below</i>)</tt><br />
<tt>    requires Swappable&lt;Base&amp;&gt;();</tt><br />
<tt>};</tt></p>
</blockquote>
<p>Update the specifications of the functions in [taggedtup.tagged] to agree with the synopsis.</p>
<p>Change the synopsis of the header <code>&lt;experimental/ranges/iterator&gt;</code> in [iterator.synopsis] as follows:</p>
<blockquote>
<p><tt>// 6.6.5, iterator operations:</tt><br />
<tt>template &lt;Iterator I&gt;</tt><br />
<tt>  <ins>constexpr </ins>void advance(I&amp; i, difference_type_t&lt;I&gt; n);</tt><br />
<tt>template &lt;Iterator I, Sentinel&lt;I&gt; S&gt;</tt><br />
<tt>  <ins>constexpr </ins>void advance(I&amp; i, S bound);</tt><br />
<tt>template &lt;Iterator I, Sentinel&lt;I&gt; S&gt;</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;I&gt; advance(I&amp; i, difference_type_t&lt;I&gt; n, S bound);</tt><br />
<tt>template &lt;Iterator I, Sentinel&lt;I&gt; S&gt;</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;I&gt; distance(I first, S last);</tt><br />
<tt>template &lt;Iterator I&gt;</tt><br />
<tt>  <ins>constexpr </ins>I next(I x, difference_type_t&lt;I&gt; n = 1);</tt><br />
<tt>template &lt;Iterator I, Sentinel&lt;I&gt; S&gt;</tt><br />
<tt>  <ins>constexpr </ins>I next(I x, S bound);</tt><br />
<tt>template &lt;Iterator I, Sentinel&lt;I&gt; S&gt;</tt><br />
<tt>  <ins>constexpr </ins>I next(I x, difference_type_t&lt;I&gt; n, S bound);</tt><br />
<tt>template &lt;BidirectionalIterator I&gt;</tt><br />
<tt>  <ins>constexpr </ins>I prev(I x, difference_type_t&lt;I&gt; n = 1);</tt><br />
<tt>template &lt;BidirectionalIterator I&gt;</tt><br />
<tt>  <ins>constexpr </ins>I prev(I x, difference_type_t&lt;I&gt; n, I bound);</tt></p>
<p>[…]</p>
<p><tt>// 6.7, predefined iterators and sentinels:</tt></p>
<p><tt>// 6.7.1, reverse iterators:</tt><br />
<tt>template &lt;BidirectionalIterator I&gt; class reverse_iterator;</tt></p>
<p><tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires EqualityComparable&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator==(</tt><br />
<tt>    const reverse_iterator&lt;I1&gt;&amp; x,</tt><br />
<tt>    const reverse_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires EqualityComparable&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator!=(</tt><br />
<tt>    const reverse_iterator&lt;I1&gt;&amp; x,</tt><br />
<tt>    const reverse_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires StrictTotallyOrdered&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&lt;(</tt><br />
<tt>    const reverse_iterator&lt;I1&gt;&amp; x,</tt><br />
<tt>    const reverse_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires StrictTotallyOrdered&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&gt;(</tt><br />
<tt>    const reverse_iterator&lt;I1&gt;&amp; x,</tt><br />
<tt>    const reverse_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires StrictTotallyOrdered&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&gt;=(</tt><br />
<tt>    const reverse_iterator&lt;I1&gt;&amp; x,</tt><br />
<tt>    const reverse_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires StrictTotallyOrdered&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&lt;=(</tt><br />
<tt>    const reverse_iterator&lt;I1&gt;&amp; x,</tt><br />
<tt>    const reverse_iterator&lt;I2&gt;&amp; y);</tt></p>
<p><tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires SizedSentinel&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;I2&gt; operator-(</tt><br />
<tt>    const reverse_iterator&lt;I1&gt;&amp; x,</tt><br />
<tt>    const reverse_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;RandomAccessIterator I&gt;</tt><br />
<tt>  <ins>constexpr </ins>reverse_iterator&lt;I&gt; operator+(</tt><br />
<tt>    difference_type_t&lt;I&gt; n,</tt><br />
<tt>    const reverse_iterator&lt;I&gt;&amp; x);</tt></p>
<p><tt>template &lt;BidirectionalIterator I&gt;</tt><br />
<tt>  <ins>constexpr </ins>reverse_iterator&lt;I&gt; make_reverse_iterator(I i);</tt></p>
<p>[…]</p>
<p><tt>// 6.7.3, move iterators and sentinels:</tt><br />
<tt>template &lt;InputIterator I&gt; class move_iterator;</tt></p>
<p><tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires EqualityComparable&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator==(</tt><br />
<tt>    const move_iterator&lt;I1&gt;&amp; x, const move_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires EqualityComparable&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator!=(</tt><br />
<tt>    const move_iterator&lt;I1&gt;&amp; x, const move_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires StrictTotallyOrdered&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&lt;(</tt><br />
<tt>    const move_iterator&lt;I1&gt;&amp; x, const move_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires StrictTotallyOrdered&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&lt;=(</tt><br />
<tt>    const move_iterator&lt;I1&gt;&amp; x, const move_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires StrictTotallyOrdered&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&gt;(</tt><br />
<tt>    const move_iterator&lt;I1&gt;&amp; x, const move_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires StrictTotallyOrdered&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&gt;=(</tt><br />
<tt>    const move_iterator&lt;I1&gt;&amp; x, const move_iterator&lt;I2&gt;&amp; y);</tt></p>
<p><tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires SizedSentinel&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;I2&gt; operator-(</tt><br />
<tt>    const move_iterator&lt;I1&gt;&amp; x,</tt><br />
<tt>    const move_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;RandomAccessIterator I&gt;</tt><br />
<tt>  <ins>constexpr </ins>move_iterator&lt;I&gt; operator+(</tt><br />
<tt>    difference_type_t&lt;I&gt; n,</tt><br />
<tt>    const move_iterator&lt;I&gt;&amp; x);</tt><br />
<tt>template &lt;InputIterator I&gt;</tt><br />
<tt>  <ins>constexpr </ins>move_iterator&lt;I&gt; make_move_iterator(I i);</tt></p>
<p><tt>template &lt;Semiregular S&gt; class move_sentinel;</tt></p>
<p><tt>template &lt;class I, Sentinel&lt;I&gt; S&gt;</tt><br />
<tt>  <ins>constexpr </ins>bool operator==(</tt><br />
<tt>    const move_iterator&lt;I&gt;&amp; i,</tt><br />
<tt>    const move_sentinel&lt;S&gt;&amp; s);</tt><br />
<tt>template &lt;class I, Sentinel&lt;I&gt; S&gt;</tt><br />
<tt>  <ins>constexpr </ins>bool operator==(</tt><br />
<tt>    const move_sentinel&lt;S&gt;&amp; s,</tt><br />
<tt>    const move_iterator&lt;I&gt;&amp; i);</tt><br />
<tt>template &lt;class I, Sentinel&lt;I&gt; S&gt;</tt><br />
<tt>  <ins>constexpr </ins>bool operator!=(</tt><br />
<tt>    const move_iterator&lt;I&gt;&amp; i,</tt><br />
<tt>    const move_sentinel&lt;S&gt;&amp; s);</tt><br />
<tt>template &lt;class I, Sentinel&lt;I&gt; S&gt;</tt><br />
<tt>  <ins>constexpr </ins>bool operator!=(</tt><br />
<tt>    const move_sentinel&lt;S&gt;&amp; s,</tt><br />
<tt>    const move_iterator&lt;I&gt;&amp; i);</tt></p>
<p><tt>template &lt;class I, SizedSentinel&lt;I&gt; S&gt;</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;I&gt; operator-(</tt><br />
<tt>    const move_sentinel&lt;S&gt;&amp; s, const move_iterator&lt;I&gt;&amp; i);</tt><br />
<tt>template &lt;class I, SizedSentinel&lt;I&gt; S&gt;</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;I&gt; operator-(</tt><br />
<tt>    const move_iterator&lt;I&gt;&amp; i, const move_sentinel&lt;S&gt;&amp; s);</tt></p>
<p><tt>template &lt;Semiregular S&gt;</tt><br />
<tt>  <ins>constexpr </ins>move_sentinel&lt;S&gt; make_move_sentinel(S s);</tt></p>
<p>[…]</p>
<p><tt>// 6.7.6, counted iterators:</tt><br />
<tt>template &lt;Iterator I&gt; class counted_iterator;</tt></p>
<p><tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires Common&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator==(</tt><br />
<tt>    const counted_iterator&lt;I1&gt;&amp; x, const counted_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt><ins>constexpr </ins>bool operator==(</tt><br />
<tt>  const counted_iterator&lt;auto&gt;&amp; x, default_sentinel);</tt><br />
<tt><ins>constexpr </ins>bool operator==(</tt><br />
<tt>  default_sentinel, const counted_iterator&lt;auto&gt;&amp; x);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires Common&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator!=(</tt><br />
<tt>    const counted_iterator&lt;I1&gt;&amp; x, const counted_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt><ins>constexpr </ins>bool operator!=(</tt><br />
<tt>  const counted_iterator&lt;auto&gt;&amp; x, default_sentinel y);</tt><br />
<tt><ins>constexpr </ins>bool operator!=(</tt><br />
<tt>  default_sentinel x, const counted_iterator&lt;auto&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires Common&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&lt;(</tt><br />
<tt>    const counted_iterator&lt;I1&gt;&amp; x, const counted_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires Common&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&lt;=(</tt><br />
<tt>    const counted_iterator&lt;I1&gt;&amp; x, const counted_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires Common&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&gt;(</tt><br />
<tt>    const counted_iterator&lt;I1&gt;&amp; x, const counted_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires Common&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>bool operator&gt;=(</tt><br />
<tt>    const counted_iterator&lt;I1&gt;&amp; x, const counted_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I1, class I2&gt;</tt><br />
<tt>    requires Common&lt;I1, I2&gt;()</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;I2&gt; operator-(</tt><br />
<tt>    const counted_iterator&lt;I1&gt;&amp; x, const counted_iterator&lt;I2&gt;&amp; y);</tt><br />
<tt>template &lt;class I&gt;</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;I&gt; operator-(</tt><br />
<tt>    const counted_iterator&lt;I&gt;&amp; x, default_sentinel y);</tt><br />
<tt>template &lt;class I&gt;</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;I&gt; operator-(</tt><br />
<tt>    default_sentinel x, const counted_iterator&lt;I&gt;&amp; y);</tt></p>
<p><tt>template &lt;RandomAccessIterator I&gt;</tt><br />
<tt>  <ins>constexpr </ins>counted_iterator&lt;I&gt; operator+(</tt><br />
<tt>    difference_type_t&lt;I&gt; n, const counted_iterator&lt;I&gt;&amp; x);</tt><br />
<tt>template &lt;Iterator I&gt;</tt><br />
<tt>  <ins>constexpr </ins>counted_iterator&lt;I&gt; make_counted_iterator(I i, difference_type_t&lt;I&gt; n);</tt><br />
<tt>template &lt;Iterator I&gt;</tt><br />
<tt>  <ins>constexpr </ins>void advance(counted_iterator&lt;I&gt;&amp; i, difference_type_t&lt;I&gt; n);</tt></p>
<p>[…]</p>
<p><tt>// 6.11, range primitives:</tt><br />
<tt>namespace {</tt><br />
<tt>  constexpr <i>unspecified</i> size = <i>unspecified</i>;</tt><br />
<tt>  constexpr <i>unspecified</i> empty = <i>unspecified</i>;</tt><br />
<tt>  constexpr <i>unspecified</i> data = <i>unspecified</i>;</tt><br />
<tt>  constexpr <i>unspecified</i> cdata = <i>unspecified</i>;</tt><br />
<tt>}</tt><br />
<tt>template &lt;Range R&gt;</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;iterator_t&lt;R&gt;&gt; distance(R&amp;&amp; r);</tt><br />
<tt>template &lt;SizedRange R&gt;</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;iterator_t&lt;R&gt;&gt; distance(R&amp;&amp; r);</tt></p>
</blockquote>
<p>Update the specifications of the functions in [iterator.operations], [reverse.iterator], [iterators.move], [move.sentinel], [iterators.counted], and [range.primitives] to agree with the synopsis.</p>
<p>In [reverse.iterator], change the synopsis of class template <code>reverse_iterator</code> as follows:</p>
<blockquote>
<p><tt>template &lt;BidirectionalIterator I&gt;</tt><br />
<tt>class reverse_iterator {</tt><br />
<tt>public:</tt><br />
<tt>  using iterator_type = I;</tt><br />
<tt>  using difference_type = difference_type_t&lt;I&gt;;</tt><br />
<tt>  using value_type = value_type_t&lt;I&gt;;</tt><br />
<tt>  using iterator_category = iterator_category_t&lt;I&gt;;</tt><br />
<tt>  using reference = reference_t&lt;I&gt;;</tt><br />
<tt>  using pointer = I;</tt></p>
<p><tt>  <ins>constexpr </ins>reverse_iterator();</tt><br />
<tt>  <ins>constexpr </ins>explicit reverse_iterator(I x);</tt><br />
<tt>  <ins>constexpr </ins>reverse_iterator(const reverse_iterator&lt;ConvertibleTo&lt;I&gt;&gt;&amp; i);</tt><br />
<tt>  <ins>constexpr </ins>reverse_iterator&amp; operator=(const reverse_iterator&lt;ConvertibleTo&lt;I&gt;&gt;&amp; i);</tt></p>
<p><tt>  <ins>constexpr </ins>I base() const;</tt><br />
<tt>  <ins>constexpr </ins>reference operator*() const;</tt><br />
<tt>  <ins>constexpr </ins>pointer operator-&gt;() const;</tt></p>
<p><tt>  <ins>constexpr </ins>reverse_iterator&amp; operator++();</tt><br />
<tt>  <ins>constexpr </ins>reverse_iterator operator++(int);</tt><br />
<tt>  <ins>constexpr </ins>reverse_iterator&amp; operator--();</tt><br />
<tt>  <ins>constexpr </ins>reverse_iterator operator--(int);</tt></p>
<p><tt>  <ins>constexpr </ins>reverse_iterator operator+ (difference_type n) const</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>reverse_iterator&amp; operator+=(difference_type n)</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>reverse_iterator operator- (difference_type n) const</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>reverse_iterator&amp; operator-=(difference_type n)</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>reference operator[](difference_type n) const</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>private:</tt><br />
<tt>  I current; // exposition only</tt><br />
<tt>};</tt></p>
</blockquote>
<p>Update the specifications of the member functions in [reverse.iterator] to agree with the class template synopsis.</p>
<p>In [move.iterator], change the synopsis of class template <code>move_iterator</code> as follows:</p>
<blockquote>
<p><tt>template &lt;InputIterator I&gt;</tt><br />
<tt>class move_iterator {</tt><br />
<tt>public:</tt><br />
<tt>  using iterator_type = I;</tt><br />
<tt>  using difference_type = difference_type_t&lt;I&gt;;</tt><br />
<tt>  using value_type = value_type_t&lt;I&gt;;</tt><br />
<tt>  using iterator_category = input_iterator_tag;</tt><br />
<tt>  using reference = <i>see below</i>;</tt></p>
<p><tt>  move_iterator();</tt><br />
<tt>  <ins>constexpr </ins>explicit move_iterator(I i);</tt><br />
<tt>  <ins>constexpr </ins>move_iterator(const move_iterator&lt;ConvertibleTo&lt;I&gt;&gt;&amp; i);</tt><br />
<tt>  <ins>constexpr </ins>move_iterator&amp; operator=(const move_iterator&lt;ConvertibleTo&lt;I&gt;&gt;&amp; i);</tt></p>
<p><tt>  <ins>constexpr </ins>I base() const;</tt><br />
<tt>  <ins>constexpr </ins>reference operator*() const;</tt></p>
<p><tt>  <ins>constexpr </ins>move_iterator&amp; operator++();</tt><br />
<tt>  <ins>constexpr </ins>move_iterator operator++(int);</tt><br />
<tt>  <ins>constexpr </ins>move_iterator&amp; operator–()</tt><br />
<tt>    requires BidirectionalIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>move_iterator operator–(int)</tt><br />
<tt>    requires BidirectionalIterator&lt;I&gt;();</tt></p>
<p><tt>  <ins>constexpr </ins>move_iterator operator+(difference_type n) const</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>move_iterator&amp; operator+=(difference_type n)</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>move_iterator operator-(difference_type n) const</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>move_iterator&amp; operator-=(difference_type n)</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>reference operator[](difference_type n) const</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt></p>
<p><tt>private:</tt><br />
<tt>  I current; // exposition only</tt><br />
<tt>};</tt></p>
</blockquote>
<p>Update the specifications of the member functions in [move.iterator] to agree with the class template synopsis.</p>
<p>In [common.iterator], change the synopsis of class template <code>common_iterator</code> as follows:</p>
<blockquote>
<p><tt>template &lt;Iterator I, Sentinel&lt;I&gt; S&gt;</tt><br />
<tt>  requires !Same&lt;I, S&gt;()</tt><br />
<tt>class common_iterator {</tt><br />
<tt>public:</tt><br />
<tt>  using difference_type = difference_type_t&lt;I&gt;;</tt></p>
<p><tt>  <ins>constexpr </ins>common_iterator();</tt><br />
<tt>  <ins>constexpr </ins>common_iterator(I i);</tt><br />
<tt>  <ins>constexpr </ins>common_iterator(S s);</tt><br />
<tt>  <ins>constexpr </ins>common_iterator(const common_iterator&lt;ConvertibleTo&lt;I&gt;, ConvertibleTo&lt;S&gt;&gt;&amp; u);</tt><br />
<tt>  common_iterator&amp; operator=(const common_iterator&lt;ConvertibleTo&lt;I&gt;, ConvertibleTo&lt;S&gt;&gt;&amp; u);</tt></p>
<p><tt>  ~common_iterator();</tt></p>
<p><tt>  <i>see below</i> operator*();</tt><br />
<tt>  <i>see below</i> operator*() const;</tt><br />
<tt>  <i>see below</i> operator-&gt;() const requires Readable&lt;I&gt;();</tt></p>
<p><tt>  common_iterator&amp; operator++();</tt><br />
<tt>  common_iterator operator++(int);</tt></p>
<p><tt>private:</tt><br />
<tt>  bool is_sentinel; // exposition only</tt><br />
<tt>  I iter; // exposition only</tt><br />
<tt>  S sentinel; // exposition only</tt><br />
<tt>};</tt></p>
</blockquote>
<p>Update the specifications of the member functions in [common.iterator] to agree with the class template synopsis.</p>
<p>In [counted.iterator], change the synopsis of class template <code>counted_iterator</code> as follows:</p>
<blockquote>
<p><tt>template &lt;Iterator I&gt;</tt><br />
<tt>class counted_iterator {</tt><br />
<tt>public:</tt><br />
<tt>  using iterator_type = I;</tt><br />
<tt>  using difference_type = difference_type_t&lt;I&gt;;</tt></p>
<p><tt>  <ins>constexpr </ins>counted_iterator();</tt><br />
<tt>  <ins>constexpr </ins>counted_iterator(I x, difference_type_t&lt;I&gt; n);</tt><br />
<tt>  <ins>constexpr </ins>counted_iterator(const counted_iterator&lt;ConvertibleTo&lt;I&gt;&gt;&amp; i);</tt><br />
<tt>  <ins>constexpr </ins>counted_iterator&amp; operator=(const counted_iterator&lt;ConvertibleTo&lt;I&gt;&gt;&amp; i);</tt></p>
<p><tt>  <ins>constexpr </ins>I base() const;</tt><br />
<tt>  <ins>constexpr </ins>difference_type_t&lt;I&gt; count() const;</tt><br />
<tt>  <ins>constexpr </ins><i>see below</i> operator*();</tt><br />
<tt>  <ins>constexpr </ins><i>see below</i> operator*() const;</tt></p>
<p><tt>  <ins>constexpr </ins>counted_iterator&amp; operator++();</tt><br />
<tt>  <ins>constexpr </ins>counted_iterator operator++(int);</tt><br />
<tt>  <ins>constexpr </ins>counted_iterator&amp; operator--()</tt><br />
<tt>    requires BidirectionalIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>counted_iterator operator--(int)</tt><br />
<tt>    requires BidirectionalIterator&lt;I&gt;();</tt></p>
<p><tt>  <ins>constexpr </ins>counted_iterator operator+ (difference_type n) const</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>counted_iterator&amp; operator+=(difference_type n)</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>counted_iterator operator- (difference_type n) const</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins>counted_iterator&amp; operator-=(difference_type n)</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>  <ins>constexpr </ins><i>see below</i> operator[](difference_type n) const</tt><br />
<tt>    requires RandomAccessIterator&lt;I&gt;();</tt><br />
<tt>private:</tt><br />
<tt>  I current; // exposition only</tt><br />
<tt>  difference_type_t&lt;I&gt; cnt; // exposition only</tt><br />
<tt>};</tt></p>
</blockquote>
<p>Update the specifications of the member functions in [counted.iterator] to agree with the class template synopsis.</p>
<p>In [dangling.wrap], change the synopsis of class template <code>dangling</code> as follows:</p>
<blockquote>
<p><tt>template &lt;CopyConstructible T&gt;</tt><br />
<tt>class dangling {</tt><br />
<tt>public:</tt><br />
<tt>  <ins>constexpr </ins>dangling() requires DefaultConstructible&lt;T&gt;();</tt><br />
<tt>  <ins>constexpr </ins>dangling(T t);</tt><br />
<tt>  <ins>constexpr </ins>T get_unsafe() const;</tt><br />
<tt>private:</tt><br />
<tt>  T value; // exposition only</tt><br />
<tt>};</tt></p>
</blockquote>
<p>Update the specifications of the member functions in [dangling.wrap.ops] to agree with the class template synopsis.</p>
</body>
</html>
