<!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>Ranges TS: Post-Increment on Input and Output Iterators</title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
  margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
  </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">
      P0541
    </td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Date:</td>
    <td width="435">2017-02-02</td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Project:</td>
    <td width="435">C++ Extensions for Ranges</td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Reply-to:</td>
    <td width="435">
      Eric Niebler &lt;<a href="mailto:eniebler@boost.org">eniebler@boost.org</a>&gt;
    </td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Audience:</td>
    <td width="435">
      Library Working Group
    </td>
  </tr>
</table>
<div id="header">
<h1 class="title">Ranges TS: Post-Increment on Input and Output Iterators</h1>
</div>
<div id="TOC">
<ul>
<li><a href="#synopsis"><span class="toc-section-number">1</span> Synopsis</a></li>
<li><a href="#input-iterators"><span class="toc-section-number">2</span> Input Iterators</a><ul>
<li><a href="#the-problem"><span class="toc-section-number">2.1</span> The Problem</a><ul>
<li><a href="#operator-expense"><span class="toc-section-number">2.1.1</span> Operator Expense</a></li>
<li><a href="#adaptor-complications"><span class="toc-section-number">2.1.2</span> Adaptor Complications</a></li>
</ul></li>
<li><a href="#alternative-solutions"><span class="toc-section-number">2.2</span> Alternative Solutions</a><ul>
<li><a href="#do-nothing"><span class="toc-section-number">2.2.1</span> Do nothing</a></li>
<li><a href="#remove-postfix-increment-entirely"><span class="toc-section-number">2.2.2</span> Remove postfix increment entirely</a></li>
</ul></li>
</ul></li>
<li><a href="#output-iterators"><span class="toc-section-number">3</span> Output Iterators</a></li>
<li><a href="#proposed-design"><span class="toc-section-number">4</span> Proposed Design</a></li>
<li><a href="#acknowledgements"><span class="toc-section-number">5</span> Acknowledgements</a></li>
</ul>
</div>
<h1 id="synopsis"><span class="header-section-number">1</span> Synopsis</h1>
<p>The requirement for InputIterators to provide a post-increment operator that returns a type satisfying the Readable concept presents significant implementation challenges for many Input iterators, and makes some impossible to implement. This paper suggests removing the requirement for InputIterators. Specifically, we propose lifting the requirement that the return type of the post-increment operator for <code>InputIterator</code> satisfy <code>Readable</code>. We retain the requirement for forward iterators.</p>
<p>Note that nothing would prevent a given input iterator from supporting the syntax <code>*i++</code> or prevent non-generic code from making use of that syntax. The only change would be that generic code that operates on input iterators would need to change statements like <code>fn(*i++)</code> to <code>fn(*i); ++i</code>. This is likely to be more efficient, as is discussed below.</p>
<p>In Issaquah, the problem was discussed and a straw poll taken. The wording of the poll was as follows:</p>
<blockquote>
<p>Do we want to loosen the requirement on <code>InputIterator</code> post-increment to permit <code>void</code> return?</p>
<table>
<thead>
<tr class="header">
<th>SF</th>
<th>F</th>
<th>N</th>
<th>A</th>
<th>SA</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>13</td>
<td>6</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
</tbody>
</table>
</blockquote>
<h1 id="input-iterators"><span class="header-section-number">2</span> Input Iterators</h1>
<h2 id="the-problem"><span class="header-section-number">2.1</span> The Problem</h2>
<p>Iterator post-increment requires that the expression <code>*i++</code> advances the iterator but returns the previous value. For forward iterators, that is trivially implementable by having the expression <code>i++</code> return a copy of the iterator before the application of <em>pre</em>-increment; e.g., <code>{ auto tmp = i; ++i; return tmp; }</code>. This doesn’t work for InputIterators because pre-increment invalidates all copies of the iterator. When considering an iterator like <code>istreambuf_iterator</code> it is easy to see why: incrementing reads from a stream, thereby consuming the range as it is traversed.</p>
<p>In order for an iterator like <code>istreambuf_iterator</code> to give the expression <code>*i++</code> the required semantics, <code>i++</code> must return a proxy object that caches the previous value within it, and returns a reference to the previous value from an overloaded unary <code>operator*</code>. This proxy object must satisfy the <code>Readable</code> concept for <code>istreambuf_iterator</code> to satisfy the <code>InputIterator</code> concept in the Ranges TS.</p>
<h3 id="operator-expense"><span class="header-section-number">2.1.1</span> Operator Expense</h3>
<p><code>Readable</code> requires <code>Movable</code> and <code>DefaultConstructible</code>. For value types that are not themselves <code>Movable</code> or <code>DefaultConstructible</code>, various hacks are necessary for the proxy object to satisfy the concepts; e.g., storing the previous value in a <code>std::optional</code> or on the heap. Types that are not efficiently movable (e.g., <code>std::array</code>) are copied into the proxy object at great runtime cost, a cost that is hidden in the innocuous-looking expression <code>i++</code>.</p>
<p>Types that are <em>not</em> movable simply cannot be cached. An input iterator over non-movable types is simply disallowed by the requirements on <code>operator++(int)</code>.</p>
<h3 id="adaptor-complications"><span class="header-section-number">2.1.2</span> Adaptor Complications</h3>
<p>The standard specifies the existence of several iterator adaptors (e.g., <code>move_iterator</code>), and future iterations of the Ranges TS will propose many more. <code>move_iterator</code> is required to work with input iterators. Consider the difficulty of impementing <code>move_iterator</code>’s postfix increment operator. Below is the implementation as specified in the current draft standard.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;InputIterator I&gt;
move_iterator&lt;I&gt; move_iterator&lt;I&gt;::<span class="kw">operator</span>++(<span class="dt">int</span>) {
    <span class="kw">auto</span> tmp = *<span class="kw">this</span>;
    ++<span class="kw">this</span>-&gt;current; <span class="co">// A data member of type I</span>
    <span class="kw">return</span> tmp;
}</code></pre></div>
<p>This implementation is obviously wrong for input iterators – it is guaranteed to return an invalid iterator – and yet this is precisely what the standard specifies today. Correcting the problem is non-trivial. <code>move_iterator</code>’s postfix increment operator would need to return a proxy for input iterators only. Below is a rough demonstration, expressed in C++17.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;InputIterator I&gt;
<span class="kw">auto</span> move_iterator&lt;I&gt;::<span class="kw">operator</span>++(<span class="dt">int</span>) {
    <span class="kw">using</span> _Cat = iterator_category;
    <span class="kw">if</span> <span class="kw">constexpr</span> (is_base_of_v&lt;forward_iterator_tag, _Cat&gt;) {
        <span class="co">// Forward iterators permit a simple implementation</span>
        <span class="kw">return</span> move_iterator{<span class="kw">this</span>-&gt;current++};
    } <span class="kw">else</span> {
        <span class="co">// Input iterators must return a proxy</span>
        <span class="kw">using</span> _R = decay_t&lt;<span class="kw">decltype</span>(<span class="kw">this</span>-&gt;current++)&gt;;
        <span class="kw">struct</span> __proxy {
            <span class="kw">using</span> value_type = value_type_t&lt;_R&gt;;
            <span class="kw">using</span> _Ref = reference_t&lt;_R&gt;;
            <span class="kw">using</span> reference = conditional_t&lt;
                is_reference_v&lt;_Ref&gt;,
                remove_reference_t&lt;_Ref&gt;&amp;&amp;,
                decay_t&lt;_Ref&gt;&gt;;
            _R __cache;
            reference <span class="kw">operator</span>*() <span class="dt">const</span> {
                <span class="kw">return</span> <span class="kw">static_cast</span>&lt;reference&gt;(*__cache);
            }
        };
        <span class="kw">return</span> __proxy{<span class="kw">this</span>-&gt;current++};
    }
}</code></pre></div>
<p>The very fact that the C++ standard gets this wrong for <code>move_iterator</code> demonstrates the complex subtlety that the requirement introduces into the standard iterator concepts.</p>
<p>The problem is even worse for other iterator adaptors. Imagine an adaptor that transforms its base iterator’s reference somehow. Just because the iterator knows how to transform the base iterator’s reference type is no guarantee that it knows how to transform its postfix-increment proxy reference type. In other words, for some transformation <code>TFX</code>, the well-formedness of <code>TFX(*it)</code> doesn’t ensure the well-formedness of <code>TFX(*it++)</code>. That’s because the types of the expressions <code>*it</code> and <code>*it++</code> are not required to be the same for input iterators. For example, <code>*it</code> might be an <code>int&amp;</code>, but <code>*it++</code> might be an <code>int</code>.</p>
<p>In other words, due to the inherent oddness of the postfix increment operator, it is impossible to implement a generic iterator adaptor for all valid input iterators.</p>
<h2 id="alternative-solutions"><span class="header-section-number">2.2</span> Alternative Solutions</h2>
<p>The following solutions have been considered and dismissed.</p>
<h3 id="do-nothing"><span class="header-section-number">2.2.1</span> Do nothing</h3>
<p>One obvious solution is to simply do nothing. We have lived with the oddness of input iterator’s postfix increment operator long enough. We can continue to live with it in the Ranges TS and beyond. Some generic iterator adaptors will be impossible to get completely correct, but its likely to be corner cases that will fail. Again, probably not a <em>huge</em> deal. Despite the preceeding, we have decided to push forward our suggested resolution because with Concepts we have a chance to correct various shortcomings of the iterator concepts. Now is the time for any breaking changes. This change sweeps away the necessity for a lot of needless complexity in iterator implementations, and steers users away from using a surprisingly expensive iterator operation.</p>
<p>With the Ranges TS, we have a chance to try out this change without fully committing to it. Should the lack of <code>*i++</code> prove to be an adoption challenge, we would still have time to add it back in should the Ranges TS ever be merged into the IS.</p>
<h3 id="remove-postfix-increment-entirely"><span class="header-section-number">2.2.2</span> Remove postfix increment entirely</h3>
<p>During the Issaquah 2016 meeting when this issue was discussed in LEWG, several in the room expressed support for the notion of simply removing postfix increment for input iterators entirely. (This is in contrast with requiring postfix increment but permitting it to return, say, <code>void</code>.) The following straw poll was taken on that question:</p>
<blockquote>
<p>Do we want to remove the requirement for InputIterator post-increment entirely (for the Ranges TS)?</p>
<table>
<thead>
<tr class="header">
<th>SF</th>
<th>F</th>
<th>N</th>
<th>A</th>
<th>SA</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>7</td>
<td>6</td>
<td>7</td>
<td>2</td>
<td>0</td>
</tr>
</tbody>
</table>
</blockquote>
<p>Although there does appear to be weak consensus to remove <code>i++</code> entirely from the <code>InputIterator</code> concept, the consensus to keep <code>i++</code> but permit it to return <code>void</code> is stronger.</p>
<p>The authors of the Ranges TS strongly prefer keeping the postfix increment operator for input iterators. Consider the following fairly common (anti-)pattern:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">for</span> (<span class="kw">auto</span> i = v.begin(); i != v.end(); i++) {
    <span class="co">// ...</span>
}</code></pre></div>
<p>Aside from concerns over the cost of post-increment, there is nothing wrong with this code <em>per se</em>, and the authors see no compelling reason to break it. And by permitting <code>i++</code> to return <code>void</code>, we would actually be mitigating the performance problem.</p>
<h1 id="output-iterators"><span class="header-section-number">3</span> Output Iterators</h1>
<p>After considering the issue for input iterators, its natural to wonder what the situation is for output iterators. Should <code>OutputIterator</code> require writabilty for the expression <code>o++</code>? The present draft of the Ranges TS places no requirements on the expression <code>o++</code>, making the expression <code>*o++ = t</code> non-portable in generic code. Perhaps we should add it.</p>
<p>On the one hand, output iterators need not cache any previous value in the result of <code>o++</code> to give <code>*o++ = t</code> the correct semantics. As a result, there is no performance problem with postfix increment, and no known difficulty adapting output iterators. <em>Not</em> supporting writability for <code>o++</code> would seem to be a needless incompatibiliity with the iterators in the IS. We don’t know of an output iterator for which the postfix increment operator is not completely trivial and efficient.</p>
<p>On the other hand, its hard to say with certainty that there will <em>never</em> be an output iterator with an expensive and complicated postfix increment. And supporting <code>*o++</code> for output iterators but not for input iterators is inconsistent and confusing.</p>
<p>Avoiding needless breakage <em>seems</em> like the more convincing argument. Neither of the authors of the Ranges TS has any strong opinions on the matter, but this paper suggests adding back the writability requirement on <code>o++</code>.</p>
<h1 id="proposed-design"><span class="header-section-number">4</span> Proposed Design</h1>
<p>Change the definition of <code>InputIterator</code> ([iterators.input]) as follows:</p>
<blockquote>
<p><tt>template &lt;class I&gt;</tt><br />
<tt>concept bool InputIterator() {</tt><br />
<tt>  return Iterator&lt;I&gt;() &amp;&amp;</tt><br />
<tt>    Readable&lt;I&gt;() &amp;&amp;</tt><br />
<tt>    <del>requires(I i, const I ci) {</del></tt><br />
<tt>      <ins>requires {</ins> typename iterator_category_t&lt;I&gt;; <ins>} &amp;&amp;</ins></tt><br />
<tt>      <del>requires</del> DerivedFrom&lt;iterator_category_t&lt;I&gt;, input_iterator_tag&gt;();</tt><br />
<tt>      <del>{ i++ } -&gt; Readable; // not required to be equality preserving</del></tt><br />
<tt>      <del>requires Same&lt;value_type_t&lt;I&gt;, value_type_t<decltype(i++)>&gt;();</del></tt><br />
<tt>      <del>{ *ci } -&gt; const value_type_t&lt;I&gt;&amp;;</del></tt><br />
<tt>    <del>};</del></tt><br />
<tt>}</tt></p>
</blockquote>
<p><ednote>[<i>Editor’s note:</i> Note: the line <code>{ *ci } -&gt; const value_type_t&lt;I&gt;&amp;;</code> is deleted here as a drive-by fix of <a href="https://github.com/ericniebler/stl2/issues/307">stl2 issue 307</a> in which the edits necessary to support proxy iterators (P0022) were applied incompletely.]<ednote></p>
<p>Change the definition of <code>OutputIterator</code> ([iterators.output]) as follows:</p>
<blockquote>
<p><tt>template &lt;class I, class T&gt;</tt><br />
<tt>concept bool OutputIterator() {</tt><br />
<tt>  return Iterator&lt;I&gt;() &amp;&amp; Writable&lt;I, T&gt;()<del>;</del> <ins>&amp;&amp;</ins></tt><br />
<tt>    <ins>requires(I i, T&amp;&amp; t) {</ins></tt><br />
<tt>      <ins>*i++ = std::forward<T>(t); // not required to be equality preserving</ins></tt><br />
<tt>    <ins>};</ins></tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change the class synopsis of <code>insert_iterator</code> ([insert.iterator]) as follows:</p>
<blockquote>
<p><tt>namespace std { namespace experimental { namespace ranges { inline namespace v1 {</tt><br />
<tt>  template &lt;class Container&gt;</tt><br />
<tt>  class insert_iterator {</tt><br />
<tt>  public:</tt><br />
<tt>    // … as before</tt><br />
<tt>    insert_iterator<ins>&amp;</ins> operator++(int);</tt><br />
<tt>    // … as before</tt><br />
<tt>  };</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change [insert.iter.op++] as follows:</p>
<blockquote>
<p><code>insert_iterator&amp; operator++();</code><br />
<tt>insert_iterator<ins>&amp;</ins> operator++(int);</tt></p>
<blockquote>
<p>1 Returns: <code>*this.</code></p>
</blockquote>
</blockquote>
<p><ednote>[<i>Editor’s note:</i> Thus restoring the signature of <code>insert_iterator</code>’s postfix increment operator to the version in the IS.]<ednote></p>
<p>Change the class synopsis of <code>move_iterator</code> ([move.iterator]) as follows:</p>
<blockquote>
<p><tt>namespace std { namespace experimental { namespace ranges { inline namespace v1 {</tt><br />
<tt>  template &lt;InputIterator I&gt;</tt><br />
<tt>  class move_iterator {</tt><br />
<tt>  public:</tt><br />
<tt>    // … as before</tt><br />
<tt>    <del>move_iterator operator++(int);</del></tt><br />
<tt>    <ins>void operator++(int);</ins></tt><br />
<tt>    <ins>move_iterator operator++(int)</ins></tt><br />
<tt>      <ins>requires ForwardIterator&lt;I&gt;();</ins></tt><br />
<tt>    // … as before</tt><br />
<tt>  };</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change [move.iter.op.incr] as follows:</p>
<blockquote>
<p><code>move_iterator&amp; operator++();</code></p>
<blockquote>
<p>1 Effects: Equivalent to <code>++current</code>.<br />
2 Returns: <code>*this.</code></p>
</blockquote>
<p><tt><ins>void operator++(int);<ins></tt></p>
<blockquote>
<ins>
<p>3 Effects: Equivalent to <code>++current</code>.</ins></p>
</blockquote>
<p><tt>move_iterator operator++(int)<del>;</del></tt><br />
<tt>  <ins>requires ForwardIterator&lt;I&gt;();</ins></tt></p>
<blockquote>
<p>4 Effects: Equivalent to:</p>
<blockquote>
<pre><code>move_iterator tmp = *this;
++current;
return tmp;</code></pre>
</blockquote>
</blockquote>
</blockquote>
<p>Change the class synopsis of <code>common_iterator</code> ([common.iterator]) as follows:</p>
<blockquote>
<p><tt>namespace std { namespace experimental { namespace ranges { inline namespace v1 {</tt><br />
<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>    // … as before</tt><br />
<tt>    <del>common_iterator operator++(int);</del></tt><br />
<tt>    <ins><i>see below</i> operator++(int);</ins></tt><br />
<tt>    <ins>common_iterator operator++(int)</ins></tt><br />
<tt>      <ins>requires ForwardIterator&lt;I&gt;();</ins></tt><br />
<tt>    // … as before</tt><br />
<tt>  };</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change [common.iter.op.incr] as follows:</p>
<blockquote>
<p><code>common_iterator&amp; operator++();</code></p>
<blockquote>
<p>1 Requires: <code>!is_sentinel</code>.<br />
2 Effects: <ins>Equivalent to</ins> <code>++iter</code>.<br />
3 Returns: <code>*this.</code></p>
</blockquote>
<p><tt><ins>decltype(auto) operator++(int);<ins></tt></p>
<blockquote>
<ins>
<p>4 Requires: <code>!is_sentinel</code>.</ins><br />
<ins>5 Effects: Equivalent to <code>return iter++</code>.</ins></p>
</blockquote>
<p><tt>common_iterator operator++(int)<del>;</del></tt><br />
<tt>  <ins>requires ForwardIterator&lt;I&gt;();</ins></tt></p>
<blockquote>
<p>6 Requires: <code>!is_sentinel</code>.<br />
7 Effects: Equivalent to:</p>
<blockquote>
<pre><code>common_iterator tmp = *this;
++iter;
return tmp;</code></pre>
</blockquote>
</blockquote>
</blockquote>
<p><ednote>[<i>Editor’s note:</i> For input and output iterators, we return the result of <code>iter++</code> directly. That permits <code>common_iterator</code>’s postfix increment operator to work correctly with input and output iterators that return proxies (e.g., <code>istreambuf_iterator</code>) or references to <code>*this</code> (e.g., <code>insert_iterator</code>) from their postfix increment operator.]<ednote></p>
<p>Change the class synopsis of <code>counted_iterator</code> ([counted.iterator]) as follows:</p>
<blockquote>
<p><tt>namespace std { namespace experimental { namespace ranges { inline namespace v1 {</tt><br />
<tt>  template &lt;Iterator I&gt;</tt><br />
<tt>  class counted_iterator {</tt><br />
<tt>  public:</tt><br />
<tt>    // … as before</tt><br />
<tt>    <del>counted_iterator operator++(int);</del></tt><br />
<tt>    <ins><i>see below</i> operator++(int);</ins></tt><br />
<tt>    <ins>counted_iterator operator++(int)</ins></tt><br />
<tt>      <ins>requires ForwardIterator&lt;I&gt;();</ins></tt><br />
<tt>    // … as before</tt><br />
<tt>  };</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change [counted.iter.op.incr] as follows:</p>
<blockquote>
<p><code>counted_iterator&amp; operator++();</code></p>
<blockquote>
<p>1 Requires: <code>cnt &gt; 0</code>.<br />
2 Effects: Equivalent to:</p>
<blockquote>
<pre><code>++current;
--cnt</code></pre>
</blockquote>
<p>3 Returns: <code>*this.</code></p>
</blockquote>
<p><tt><ins>decltype(auto) operator++(int);<ins></tt></p>
<blockquote>
<ins>
<p>4 Requires: <code>cnt &gt; 0</code>.</ins><br />
<ins>5 Effects: Equivalent to:</ins></p>
<blockquote>
<p><tt><ins>--cnt</ins></tt><br />
<tt><ins>return current++;</ins></tt></p>
</blockquote>
</blockquote>
<p><tt>counted_iterator operator++(int)<del>;</del></tt><br />
<tt>  <ins>requires ForwardIterator&lt;I&gt;();</ins></tt></p>
<blockquote>
<p>6 Requires: <code>cnt &gt; 0</code>.<br />
7 Effects: Equivalent to:</p>
<blockquote>
<pre><code>counted_iterator tmp = *this;
++current;
--cnt;
return tmp;</code></pre>
</blockquote>
</blockquote>
</blockquote>
<p><ednote>[<i>Editor’s note:</i> For input and output iterators, we return the result of <code>current++</code> directly. That permits <code>counted_iterator</code>’s postfix increment operator to work correctly with input and output iterators that return proxies (e.g., <code>istreambuf_iterator</code>) or references to <code>*this</code> (e.g., <code>insert_iterator</code>) from their postfix increment operator.]<ednote></p>
<p>No changes to <code>istream_iterator</code> or <code>istreambuf_iterator</code>.</p>
<p><ednote>[<i>Editor’s note:</i> We suggest leaving the postfix increment operators on the <code>istream(buf)</code> iterators intact to ease migration to the Ranges TS.]<ednote></p>
<p>Change the class synopsis of <code>ostream_iterator</code> ([ostream.iterator]) as follows:</p>
<blockquote>
<p><tt>namespace std { namespace experimental { namespace ranges { inline namespace v1 {</tt><br />
<tt>  template &lt;class T, class charT = char, class traits = char_traits&lt;charT&gt;&gt;</tt><br />
<tt>  class ostream_iterator {</tt><br />
<tt>  public:</tt><br />
<tt>    // … as before</tt><br />
<tt>    ostream_iterator<ins>&amp;</ins> operator++(int);</tt><br />
<tt>    // … as before</tt><br />
<tt>  };</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change [ostream.iter.ops] as follows:</p>
<blockquote>
<p>// … as before<br />
<code>ostream_iterator&amp; operator++();</code><br />
<tt>ostream_iterator<ins>&amp;</ins> operator++(int);</tt></p>
<blockquote>
<p>3 Returns: <code>*this.</code></p>
</blockquote>
</blockquote>
<p><ednote>[<i>Editor’s note:</i> Thus restoring the signature of <code>ostream_iterator</code>’s postfix increment operator to the version in the IS.]</ednote></p>
<p>Change the class synopsis of <code>ostreambuf_iterator</code> ([ostreambuf.iterator]) as follows:</p>
<blockquote>
<p><tt>namespace std { namespace experimental { namespace ranges { inline namespace v1 {</tt><br />
<tt>  template &lt;class charT, class traits = char_traits&lt;charT&gt;&gt;</tt><br />
<tt>  class ostreambuf_iterator {</tt><br />
<tt>  public:</tt><br />
<tt>    // … as before</tt><br />
<tt>    ostreambuf_iterator<ins>&amp;</ins> operator++(int);</tt><br />
<tt>    // … as before</tt><br />
<tt>  };</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change [ostreambuf.iter.ops] as follows:</p>
<blockquote>
<p>// … as before<br />
<code>ostreambuf_iterator&amp; operator++();</code><br />
<tt>ostreambuf_iterator<ins>&amp;</ins> operator++(int);</tt></p>
<blockquote>
<p>5 Returns: <code>*this.</code></p>
</blockquote>
</blockquote>
<p><ednote>[<i>Editor’s note:</i> Thus restoring the signature of <code>ostreambuf_iterator</code>’s postfix increment operator to the version in the IS.]</ednote></p>
<h1 id="acknowledgements"><span class="header-section-number">5</span> Acknowledgements</h1>
<p>I would like to thank Casey Carter for his review feedback.</p>
<div id="refs" class="references">

</div>
</body>
</html>
