<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- saved from url=(0095)http://wiki.edg.com/twiki/pub/Wg21rapperswil2014/LibraryEvolutionWorkingGroup/N4007_updated.htm -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252">

  
  <style type="text/css">
.comment { color: #999999; font-style: italic; }
.pre { color: #000099; }
.string { color: #009900; }
.char { color: #009900; }
.float { color: #996600; }
.int { color: #999900; }
.bool { color: #000000; font-weight: bold; }
.type { color: #FF6633; }
.flow { color: #FF0000; }
.keyword { color: #990000; }
.operator { color: #663300; font-weight: bold; }
.operator { color: #663300; font-weight: bold; }
pre.code {
    border: 2px solid #666;
    background-color: #F4F4F4;
    padding-left: 10px;
    padding-top: 0px;
}
code {
    border: 2px solid #d0d0d0;
    background-color: LightYellow;
    padding: 2px;
    padding-left: 10px;
    display:table;
    white-space:pre;
    margin:2px;
    margin-bottom:10px;
}
dt
{
    font-weight: bold;
}
    
.ins {
    background-color:#A0FFA0;
}

.del {
    background-color:#FFA0A0;
    text-decoration:line-through
}    
  </style>
  <title>Delimited iterators (Rev. 4)</title>

  
<style type="text/css"></style></head>
<body>
<p>N4257<br>
Revision of N4066<br>
2014-11-04<br>
Mike Spertus, Symantec<br>
<a href="mailto:mike_spertus@symantec.com">mike_spertus@symantec.com</a><br>
Nathan Wilson<br>
<a href="mailto:nwilson20@gmail.com">nwilson20@gmail.com</a><br>
<br></p>
<h1>Delimited iterators (Rev. 4)</h1>
<p>It is extremely tempting to use <tt>ostream_iterator</tt> to, say, print
a vector like:
<code>vector&lt;int&gt; v = {1, 4, 6};
cout &lt;&lt; "(";
copy(v.begin(), v.end(), ostream_iterator&lt;int&gt;(cout, ", "));
cout &lt;&lt; ")"; <span class="comment">// Oops! Prints (1, 4, 6, )</span></code></p>
<p>The problem is that the &ldquo;delimiter&rdquo; in the <tt>ostream_iterator</tt>
constructor call is better described as a suffix than a delimiter.</p>
<h2>Proposal</h2>
    <p>We propose
a new <tt>ostream_joiner</tt> class that acts like <tt>ostream_iterator</tt>
except that the delimiter is only placed between output elements:
<code>vector&lt;int&gt; v = {1, 4, 6};
cout &lt;&lt; "(";
copy(v.begin(), v.end(), std::make_ostream_joiner(cout, ", "));
cout &lt;&lt; ")"; <span class="comment">// Prints (1, 4, 6) as desired</span></code></p>
<p></p>
<h2>Discussion</h2>
<p>In the LEWG discussion of this proposal, a delimiter style such as prefix, infix, and suffix was presented. 
</p><ul><li>Since <tt>ostream_iterator</tt> already achieves a suffix 
delimiter style, the authors have removed this support in favour of
the infix style defined in the class. We have also changed the use of 
const char* as the delimiter for basic_string&lt;charT, traits&gt;.</li></ul>
<p>In the LEWG discussion of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3581.html">N3581</a>
in Issaquah, it was pointed out that the interactions of this proposal were unexpectedly subtle, so the authors
wish to discuss the design decisions in more detail.
</p><ul><li>As pointed out in LEWG, output iterators can be defined as having <tt>void</tt> value type (&sect;24.4.1p1),
    so the type being iterated need not be specified. It is apparently included in <tt>ostream_iterator</tt> for
    stylistic reasons only. Since brevity is of the essence in most uses of convenience classes such as this,
    we choose to omit the value type from <tt>ostream_joiner</tt>.</li>
<li>Since we are changing template parameters, we reject Option 1 from N3581(add functionality to <tt>ostream_iterator</tt> instead
    of creating a new class) and create a new class instead.</li>
<li>Since <tt>ostream_joiner</tt> is necessarily stateful and iterators are <em>CopyConstructible</em> and <em>CopyAssignable</em>,
    (&sect;24.2.2p2), we need to consider what happens when <tt>ostream_joiner</tt>s are copied. According to &sect;24.2.4p2,
    &ldquo;<em>Assignment through the same value of the iterator happens only once.</em>&rdquo; (Emphasis in the original).
    At Issaquah, this was interpreted as meaning that writing to one copy of an output iterator invalidates writing through
    the original output iterator. This conveniently means that the <tt>ostream_joiner</tt> can store whether we are
    outputting the first element as a member, without the need for undesirable shared state (although it is not prohibited).</li>
<li>Another possible variant would be to have a separate prefix, infix, and suffix to the list.
    <code>copy(v.begin(), v.end(), std::ostream_joiner(cout, {"(", ", ", ")"}));</code> On the one hand,
    this may be gilding the lily. On the other hand, most of the uses we have run into would leverage this and those that don't
    could use the simpler notation, and it obviates the need for the annoying <tt>delimiter_style</tt> enum.</li>
<li>We provide a <tt>make_ostream_joiner</tt> function to simplify the deduction of template parameters as suggested by LEWG.</li>
<li>If <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3602.html">Template parameter deduction for constructors</a> is eventually adopted, we will be able to dispense with the <tt>make_</tt> prefix for notation that
    will be more concise without sacrificing clarity:<code>copy(v.begin(), v.end(), std::ostream_joiner(cout, ", "));</code></li>
</ul><p></p>
<h2>Implementation</h2>
Straightforward. I give my students a homework assignment to implement <tt>ostream_joiner</tt> every year.
<h2>Wording</h2>
Modify &sect;24.3 [iterator.synopsis] as follows:
<blockquote><pre style="padding:0;margin:0"><span class="comment">//24.6, stream iterators:</span>
template &lt;class T, class charT = char, class traits = char_traits&lt;charT&gt;,
    class Distance = ptrdiff_t&gt;
class istream_iterator;
template &lt;class T, class charT, class traits, class Distance&gt;
  bool operator==(const istream_iterator&amp;;t'T,charT,traits,Distance&gt;&amp; x,
          const istream_iterator&lt;T,charT,traits,Distance&gt;&amp; y);
template &lt;class T, class charT, class traits, class Distance&gt;
  bool operator!=(const istream_iterator&lt;T,charT,traits,Distance&gt;&amp; x,
          const istream_iterator&lt;T,charT,traits,Distance&gt;&amp; y);
          
template &lt;class charT = char, class traits = char_traits&lt;charT&gt; &gt;
    class ostream_iterator;
<span class="ins">template &lt;class DelimT, class charT = char, class traits = char_traits&lt;charT&gt; &gt;
    class ostream_joiner;</span>
<span class="ins">template &lt;class charT, class traits, class DelimT&gt;
  ostream_joiner&lt;decay_t&lt;DelimT&gt;, charT, traits&gt; make_ostream_joiner(basic_ostream&lt;charT, traits&gt;&amp; os, DelimT&amp;&amp; delimiter);</span>
template&lt;class charT, class traits = char_traits&lt;charT&gt; &gt;
class istreambuf_iterator;</pre></blockquote>
Add a section &sect;24.6.x named &ldquo;Class template ostream_joiner&rdquo; [ostream.joiner] between &sect;24.6.2 [ostream.iterator] and 
&sect;24.6.3 [istreambuf.iterator]:
    
Make &sect;24.6.x [ostream.joiner] as follows:
<blockquote><span class="ins"><b>24.6.x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class template <tt>ostream_joiner</tt> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ostream.joiner]</b><br/><br/></span>
    <span class="ins"><tt>ostream_joiner</tt> writes (using <tt>operator&lt;&lt;</tt>) successive elements onto the output stream from which it was constructed. The delimiter that it was constructed with is written to the stream between every two <tt>T</tt>s that are written. It is not possible to get a value out of the output iterator. Its only use is as an output iterator in situations like 
        <blockquote><pre><span class="ins">while (first != last)
  *result++ = *first++;</span></pre></blockquote></span></blockquote>
<blockquote><pre style="padding:0;margin:0"><span class="ins">
<tt>ostream_joiner</tt> is defined as</span> 
<blockquote><span class="ins">namespace std {
  template &lt;class DelimT, class charT = char, class traits = char_traits&lt;charT&gt; &gt;
  class ostream_joiner {
  public:
    typedef charT char_type;
    typedef traits traits_type;
    typedef basic_ostream&lt;charT,traits&gt; ostream_type;
    typedef output_iterator_tag iterator_category;
    typedef void value_type;
    typedef void difference_type;
    typedef void pointer;
    typedef void reference;

    ostream_joiner(ostream_type&amp; s, DelimT&amp;&amp; delimiter);
    ostream_joiner(ostream_type&amp; s, const DelimT&amp; delimiter);
    template&lt;typename T&gt;
    ostream_joiner&lt;DelimT, charT,traits&gt;&amp; operator=(const T&amp; value);
    ostream_joiner&lt;DelimT, charT,traits&gt;&amp; operator*();
    ostream_joiner&lt;DelimT, charT,traits&gt;&amp; operator++();
    ostream_joiner&lt;DelimT, charT,traits&gt;&amp; operator++(int);
  private:
    basic_ostream&lt;charT,traits&gt;* out_stream; <span class="comment">// exposition only</span>
    DelimT delim; <span class="comment">// exposition only</span>
    bool first_element; <span class="comment">// exposition only</span>
  };
}</span></blockquote></pre></blockquote>
<blockquote><span class="ins"><b>24.6.x.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<tt>ostream_joiner</tt> constructor&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ostream.joiner.cons]</b><br/><br/></span>
    
    <span class="ins"><tt>ostream_joiner(ostream_type&amp; s, const DelimT&amp; delimiter);</tt></span>
<blockquote><span class="ins"><em>Effects:</em> Initializes <em>out_stream</em> 
with <tt>&amp;s</tt>, <em>delim</em> with <tt>delimiter</tt>,
    and <em>first_element</em> with <tt>true</tt>.<br/><br/></span>
</blockquote>
    <span class="ins"><tt>ostream_joiner(ostream_type&amp; s, DelimT&amp;&amp; delimiter);</tt></span>
<blockquote><span class="ins"><em>Effects:</em> Initializes <em>out_stream</em> 
with <tt>&amp;s</tt>, <em>delim</em> with <tt>move(delimiter)</tt>,
    and <em>first_element</em> with <tt>true</tt>.<br/><br/></span>
</blockquote>
<span class="ins"><b>24.6.x.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<tt>ostream_joiner</tt> operations&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ostream.joiner.ops]</b><br/><br/></span>

<span class="ins"><tt>template&lt;typename T&gt;
ostream_joiner&lt;DelimT, charT, traits&gt;&amp; operator=(const T&amp; value);</tt></span>
<blockquote><span class="ins"><em>Effects:</em></span>
<blockquote><pre style="padding:0;margin:0"><span class="ins">if (!<em>first_element</em>)
   *<em>out_stream</em> &lt;&lt; <em>delim</em>;
<em>first_element</em> = false;
*<em>out_stream</em> &lt;&lt; value;
return (*this);</span></pre></blockquote></blockquote>
<br/>
    
<span class="ins"><tt>ostream_joiner&lt;DelimT, charT, traits&gt;&amp; operator*();</tt></span>
<blockquote><span class="ins"><em>Returns:</em> <tt>*this</tt></span>
</blockquote><br/>
    
<span class="ins"><tt>ostream_joiner&lt;DelimT, charT, traits&gt;&amp; operator++();</tt></span><br/>
<span class="ins"><tt>ostream_joiner&lt;DelimT, charT, traits&gt;&amp; operator++(int);</tt></span>
<blockquote><span class="ins"><em>Returns:</em> <tt>*this</tt></span>
</blockquote>
<span class="ins"><b>24.6.x.3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<tt>ostream_joiner</tt> creation function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ostream.joiner.creation]</b><br/><br/></span>
<pre><span class="ins"><tt>template &lt;class charT, class traits, class DelimT&gt;
  ostream_joiner&lt;decay_t&lt;DelimT&gt;, charT, traits&gt; make_ostream_joiner(basic_ostream&lt;charT, traits&gt;&amp; os, DelimT&amp;&amp; delimiter);</tt></span>
    <blockquote><span class="ins"><em>Returns:</em> ostream_joiner&lt;decay_t&lt;DelimT&gt;, charT, traits&gt;(os, forward&lt;DelimT&gt;(delimiter));</span></blockquote></pre>
    </blockquote></body></html>
