<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta charset="utf-8">
<title>C++ Standard Library "Review" Issues Resolved in Kona</title>
<style type="text/css">
  p {text-align:justify}
  li {text-align:justify}
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table {border-collapse: collapse;}
</style>
</head>
<body>
<h1>C++ Standard Library "Review" Issues Resolved in Kona</h1>
<table>
<tr>
<td align="left">Doc. no.</td>
<td align="left">P0610R0</td>
</tr>
<tr>
<td align="left">Date:</td>
<td align="left"><p>Revised 2017-03-04 at 22:03:08 UTC</p>
</td>
</tr>
<tr>
<td align="left">Project:</td>
<td align="left">Programming Language C++</td>
</tr>
<tr>
<td align="left">Reply to:</td>
<td align="left">Marshall Clow &lt;<a href="mailto:lwgchair@gmail.com">lwgchair@gmail.com</a>&gt;</td>
</tr>
</table>
<h2>Review Issues</h2>

<hr>
<h3><a name="2676" href="#2676">2676.</a> Provide <code>filesystem::path</code> overloads for <i>File-based streams</i></h3>
<p><b>Section:</b> 27.9 [file.streams] <b>Status:</b> <a href="lwg-active.html#Review">Review</a>
 <b>Submitter:</b> Beman Dawes <b>Opened:</b> 2016-03-16 <b>Last modified:</b> 2016-12-23</p>
<p><b>Priority: </b>2
</p>
<p><b>View all other</b> <a href="lwg-index.html#file.streams">issues</a> in [file.streams].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Review">Review</a> status.</p>
<p><b>Discussion:</b></p>
  <p>
    The constructor and <code>open</code> functions for <i>File-based streams</i> in
    27.9 [file.streams] currently provide overloads for <code>const char*</code> and
    <code>const string&amp;</code> arguments that specify the path for the file to be opened.
    With the addition of the File System TS to the standard library, these
    constructors and <code>open</code> functions need to be overloaded for <code>
      const filesystem::path&amp;
    </code> so that file-based streams can take advantage of class <code>filesystem::path</code>
    features such as support for strings of character types <code>wchar_t</code>,
    <code>char16_t</code>, and <code>char32_t</code>.
  </p>
  <p>
    The <code>
      const filesystem::path&amp; p
    </code> overload for these functions is like the
    existing <code>const string&amp;</code> overload; it simply calls the overload of
    the same function that takes a C-style string.</p>
  <p> For operating systems like POSIX
    that traffic in <code>char</code> strings for filenames, nothing more is
    required. For operating systems like Windows that traffic in <code>wchar_t</code>
    strings for filenames, an additional C-style string overload is required.
    The overload's character type needs to be specified as
    <code>std::filesystem::path::value_type</code> to also support possible future
    operating systems that traffic in <code>char16_t</code> or <code>char32_t</code> characters.
  </p>
  
  <p><b>Not recommended:</b></p>
  <p>Given the proposed constructor and <code>open</code> signatures taking
  <code>const filesystem::path&amp;</code>, it would in theory be possible to remove 
  some of the other signatures. This is not proposed because it would break ABI's, break
  user code depending on user-defined automatic conversions to the existing argument types,
  and invalidate existing documentation, books, and tutorials.</p>
  
  <p><b>Implementation experience:</b></p>
  <p>
    The Boost Filesystem library has provided header <code>&lt;boost/filesystem/fstream.hpp&gt;</code>
    implementing the proposed resolution for over a decade.
  </p>
  <p>
    The Microsoft/Dinkumware
    implementation of standard library header <code>&lt;fstream&gt;</code> has provided
    the <code>const wchar_t*</code>
    overloads for many years.
  </p>

<p><i>[2016-08-03 Chicago]</i></p>

<p>Fri PM: Move to Review</p>


<p><b>Proposed resolution:</b></p>

<p><i><span style="background-color: #E1E9FD">At the end of 27.9.1 File streams 
[</span><span style="background-color: #E1E9FD">fstreams</span><span style="background-color: #E1E9FD">] 
add a paragraph:</span></i></p>

<p>In this subclause, member functions taking arguments of <code>
const std::filesystem::path::value_type*</code> shall only be provided on systems 
where <code>std::filesystem::path::value_type</code> ([class.path]) is not <code>
char</code>. [<i>Note:</i> These functions enable class <code>path</code> 
support for systems with a wide native path character type, such as <code>
wchar_t</code>. &mdash; <i>end note</i>]</p>

<p><i><span style="background-color: #E1E9FD">Change 27.9.1.1 Class template 
basic_filebuf [filebuf] as indicated:</span></i></p>

<pre>basic_filebuf&lt;charT,traits&gt;* open(const char* s,
    ios_base::openmode mode);
<ins>basic_filebuf&lt;charT,traits&gt;* open(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode);  // wide systems only; see [fstreams]</ins> 
basic_filebuf&lt;charT,traits&gt;* open(const string&amp; s,
   ios_base::openmode mode);
<ins>basic_filebuf&lt;charT,traits&gt;* open(const filesystem::path&amp; p,</ins>
   <ins>ios_base::openmode mode);</ins></pre>
   
<p><i><span style="background-color: #E1E9FD">Change 27.9.1.4 Member functions [filebuf.members] 
as indicated:</span></i></p>

<pre>basic_filebuf&lt;charT,traits&gt;* open(const char* s,
   ios_base::openmode mode);
<ins>basic_filebuf&lt;charT,traits&gt;* open(const std::filesystem::path::value_type* s,</ins>
   <ins>ios_base::openmode mode);  // wide systems only; see [fstreams]</ins></pre>
   
<p><i><span style="background-color: #E1E9FD">To 27.9.1.4 Member functions [filebuf.members] 
add:</span></i></p>

<pre><ins>basic_filebuf&lt;charT,traits&gt;* open(const filesystem::path&amp; p,</ins>
   <ins>ios_base::openmode mode);</ins></pre>
   
<blockquote>
  <p><i>Returns:</i> <code>open(p.c_str(), mode);</code></p>
</blockquote>

  <p><i><span style="background-color: #E1E9FD">Change 27.9.1.6 Class template 
basic_ifstream [ifstream] as indicated:</span></i></p>

<pre>explicit basic_ifstream(const char* s,
    ios_base::openmode mode = ios_base::in);
<ins>explicit basic_ifstream(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::in);  // wide systems only; see [fstreams]</ins>
explicit basic_ifstream(const string&amp; s,
    ios_base::openmode mode = ios_base::in);
<ins>explicit basic_ifstream(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::in);</ins>
...
void open(const char* s,
    ios_base::openmode mode = ios_base::in);
<ins>void open(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::in);  // wide systems only; see [fstreams]</ins>
void open(const string&amp; s,
    ios_base::openmode mode = ios_base::in);
<ins>void open(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::in);</ins></pre>

<p><i><span style="background-color: #E1E9FD">Change 27.9.1.7 basic_ifstream 
constructors [ifstream.cons] as indicated:</span></i></p>

<pre>explicit basic_ifstream(const char* s,
    ios_base::openmode mode = ios_base::in);
<ins>explicit basic_ifstream(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::in);  // wide systems only; see [fstreams]</ins></pre>

<p><i><span style="background-color: #E1E9FD">To 27.9.1.7 basic_ifstream 
constructors [ifstream.cons] 
add:</span></i></p>
<pre><ins>explicit basic_ifstream(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::in);</ins></pre>
   <blockquote>
  <p><ins><i>Effects: </i>the same as <code>basic_ifstream(p.c_str(), mode)</code>.</ins></p>
</blockquote>
   
<p><i><span style="background-color: #E1E9FD">Change 27.9.1.9 Member functions [ifstream.members] 
as indicated:</span></i></p>
   
<pre>void open(const char* s,
    ios_base::openmode mode = ios_base::in);
<ins>void open(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::in);  // wide systems only; see [fstreams]</ins></pre>
   
<p><i><span style="background-color: #E1E9FD">To 27.9.1.9 Member functions [ifstream.members] 
add:</span></i></p>
<pre><ins>void open(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::in);</ins></pre>
   <blockquote>
  <p><ins><i>Effects:</i> calls <code>open(p.c_str(), mode)</code>.</ins></p>
</blockquote>

<p><i><span style="background-color: #E1E9FD">Change 27.9.1.10 Class template 
basic_ofstream [ofstream] as indicated:</span></i></p>

<pre>explicit basic_ofstream(const char* s,
    ios_base::openmode mode = ios_base::out);
<ins>explicit basic_ofstream(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::out);  // wide systems only; see [fstreams]</ins>
explicit basic_ofstream(const string&amp; s,
    ios_base::openmode mode = ios_base::out);
<ins>explicit basic_ofstream(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::out);</ins>
...
void open(const char* s,
    ios_base::openmode mode = ios_base::out);
<ins>void open(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::out);  // wide systems only; see [fstreams]</ins>
void open(const string&amp; s,
    ios_base::openmode mode = ios_base::out);
<ins>void open(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::out);</ins></pre>

<p><i><span style="background-color: #E1E9FD">Change 27.9.1.11 basic_ofstream 
constructors [ofstream.cons] as indicated:</span></i></p>

<pre>explicit basic_ofstream(const char* s,
    ios_base::openmode mode = ios_base::out);
<ins>explicit basic_ofstream(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::out);  // wide systems only; see [fstreams]</ins></pre>

<p><i><span style="background-color: #E1E9FD">To 27.9.1.11 basic_ofstream 
constructors [ofstream.cons] 
add:</span></i></p>
<pre><ins>explicit basic_ofstream(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::out);</ins></pre>
   <blockquote>
  <p><ins><i>Effects: </i>the same as <code>basic_ofstream(p.c_str(), mode)</code>.</ins></p>
</blockquote>
   
<p><i><span style="background-color: #E1E9FD">Change 27.9.1.13 Member functions [ofstream.members] 
as indicated:</span></i></p>
   
<pre>void open(const char* s,
    ios_base::openmode mode = ios_base::out);
<ins>void open(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::out);  // wide systems only; see [fstreams]</ins></pre>
   
<p><i><span style="background-color: #E1E9FD">To 27.9.1.13 Member functions [ofstream.members] 
add:</span></i></p>
<pre><ins>void open(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::out);</ins></pre>
   <blockquote>
  <p><ins><i>Effects:</i> calls <code>open(p.c_str(), mode)</code>.</ins></p>
</blockquote>

<p><i><span style="background-color: #E1E9FD">Change 27.9.1.14 Class template 
basic_fstream [fstream] as indicated:</span></i></p>

<pre>explicit basic_fstream(const char* s,
    ios_base::openmode mode = ios_base::in|ios_base::out);
<ins>explicit basic_fstream(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::in|ios_base::out);  // wide systems only; see [fstreams]</ins>
explicit basic_fstream(const string&amp; s,
    ios_base::openmode mode = ios_base::in|ios_base::out);
<ins>explicit basic_fstream(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::in|ios_base::out);</ins>
...
void open(const char* s,
    ios_base::openmode mode = ios_base::in|ios_base::out);
<ins>void open(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::in|ios_base::out);  // wide systems only; see [fstreams]</ins>
void open(const string&amp; s,
    ios_base::openmode mode = ios_base::in|ios_base::out);
<ins>void open(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::in|ios_base::out);</ins></pre>

<p><i><span style="background-color: #E1E9FD">Change 27.9.1.15 basic_fstream 
constructors [fstream.cons] as indicated:</span></i></p>

<pre>explicit basic_fstream(const char* s,
    ios_base::openmode mode = ios_base::in|ios_base::out);
<ins>explicit basic_fstream(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::in|ios_base::out);  // wide systems only; see [fstreams]</ins></pre>

<p><i><span style="background-color: #E1E9FD">To 27.9.1.15 basic_fstream 
constructors [fstream.cons] 
add:</span></i></p>
<pre><ins>explicit basic_fstream(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::in|ios_base::out);</ins></pre>
   <blockquote>
  <p><ins><i>Effects: </i>the same as <code>basic_fstream(p.c_str(), mode)</code>.</ins></p>
</blockquote>
   
<p><i><span style="background-color: #E1E9FD">Change 27.9.1.17 Member functions [fstream.members] 
as indicated:</span></i></p>
   
<pre>void open(const char* s,
    ios_base::openmode mode = ios_base::in|ios_base::out);
<ins>void open(const std::filesystem::path::value_type* s,</ins>
    <ins>ios_base::openmode mode = ios_base::in|ios_base::out);  // wide systems only; see [fstreams]</ins></pre>
   
<p><i><span style="background-color: #E1E9FD">To 27.9.1.17 Member functions [fstream.members] 
add:</span></i></p>
<pre><ins>void open(const filesystem::path&amp; p,</ins>
    <ins>ios_base::openmode mode = ios_base::in|ios_base::out);</ins></pre>
   <blockquote>
  <p><ins><i>Effects:</i> calls <code>open(p.c_str(), mode)</code>.</ins></p>
</blockquote>




<hr>
<h3><a name="2790" href="#2790">2790.</a> Missing specification of <tt>istreambuf_iterator::operator-&gt;</tt></h3>
<p><b>Section:</b> 24.6.3 [istreambuf.iterator] <b>Status:</b> <a href="lwg-active.html#Review">Review</a>
 <b>Submitter:</b> Jonathan Wakely <b>Opened:</b> 2016-11-09 <b>Last modified:</b> 2017-02-02</p>
<p><b>Priority: </b>3
</p>
<p><b>View other</b> <a href="lwg-index-open.html#istreambuf.iterator">active issues</a> in [istreambuf.iterator].</p>
<p><b>View all other</b> <a href="lwg-index.html#istreambuf.iterator">issues</a> in [istreambuf.iterator].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Review">Review</a> status.</p>
<p><b>Discussion:</b></p>
<p>
<b>Addresses GB 59</b>
<p/>
There is no specification for <tt>istreambuf_iterator::operator-&gt;</tt>. This 
operator appears to have been added for C++11 by LWG issue <a href="lwg-defects.html#659">659</a>, 
which gave the signature, but also lacked specification.
</p>

<p><i>[2016-11-08, Jonathan comments and suggests wording]</i></p>

<p>
There is no good option here, and implementations either return
<tt>nullptr</tt>, or return the address of a temporary, or don't even provide
the member at all. We took polls to decide whether to remove
<tt>istreambuf_iterator::operator-&gt;</tt>, or specify it to return <tt>nullptr</tt>, and
the preferred option was to remove it. It was noted that in the Ranges
TS input iterators no longer require <tt>operator-&gt;</tt> anyway, and the
library never tries to use it.
</p>

<p><i>[Issues Telecon 16-Dec-2016]</i></p>

<p>Move to Review</p>


<p><b>Proposed resolution:</b></p>
<p>This wording is relative to N4606.</p>

<blockquote class="note">
<p>
This reverts LWG <a href="lwg-defects.html#659">659</a>.
</p>
</blockquote>

<ol>
<li><p>Remove the note in paragraph 1 of 24.6.3 [istreambuf.iterator]:</p>
<blockquote>
<p>
The class template <tt>istreambuf_iterator</tt> defines an input iterator (24.2.3) that reads successive characters
from the streambuf for which it was constructed. <tt>operator*</tt> provides access to the current input character, if
any. <del>[<i>Note:</i> <tt>operator-&gt;</tt> may return a proxy. &mdash; <i>end note</i>]</del> Each time <tt>operator++</tt> 
is evaluated, the iterator advances to the next input character. [&hellip;]
</p>
</blockquote>
</li>

<li><p>Remove the member from the class synopsis in 24.6.3 [istreambuf.iterator]:</p>

<blockquote>
<pre>
charT operator*() const;
<del>pointer operator-&gt;() const;</del>
istreambuf_iterator&amp; operator++();
proxy operator++(int);
</pre>
</blockquote>
</li>
</ol>



<hr>
<h3><a name="2796" href="#2796">2796.</a> <tt>tuple</tt> should be a literal type</h3>
<p><b>Section:</b> 20.5.1 [tuple.general] <b>Status:</b> <a href="lwg-active.html#Review">Review</a>
 <b>Submitter:</b> Jonathan Wakely <b>Opened:</b> 2016-11-09 <b>Last modified:</b> 2017-02-02</p>
<p><b>Priority: </b>2
</p>
<p><b>View other</b> <a href="lwg-index-open.html#tuple.general">active issues</a> in [tuple.general].</p>
<p><b>View all other</b> <a href="lwg-index.html#tuple.general">issues</a> in [tuple.general].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Review">Review</a> status.</p>
<p><b>Discussion:</b></p>
<p>
<b>Addresses US 109</b>
<p/>
<tt>tuple</tt> should be a literal type if its elements are literal 
types; it fails because the destructor is not necessarily trivial. 
It should follow the form of optional and variant, and mandate a 
trivial destructor if all types in <tt>Types...</tt> have a trivial destructor. It is not 
clear if <tt>pair</tt> has the same issue, as <tt>pair</tt> specifies data 
members <tt>first</tt> and <tt>second</tt>, and appears to have an 
implicitly declared and defined destructor.
<p/>
Suggested resolution:
<p/>
Document the destructor for <tt>tuple</tt>, and mandate that 
it is trivial if each of the elements in the <tt>tuple</tt> has a 
trivial destructor. Consider whether the same 
specification is needed for <tt>pair</tt>.
</p>

<p><i>[2016-11-09, Jonathan provides wording]</i></p>


<p><i>[Issues Telecon 16-Dec-2016]</i></p>

<p>Move to Review; we think this is right, but are awaiting implementation experience.</p>


<p><b>Proposed resolution:</b></p>
<p>This wording is relative to N4606.</p>

<ol>
<li><p>Add a new paragraph after 20.4.2 [pairs.pair] p2:</p>
<blockquote>
<p>
-2- The defaulted move and copy constructor, respectively, of <tt>pair</tt> shall be a <tt>constexpr</tt> function 
if and only if all required element-wise initializations for copy and move, respectively, would satisfy the requirements for a
<tt>constexpr</tt> function. <ins>The destructor of <tt>pair</tt> shall be a trivial destructor if 
<tt>(is_trivially_destructible_v&lt;T1&gt; &amp;&amp; is_trivially_destructible_v&lt;T2&gt;)</tt> is <tt>true</tt>.</ins>
</p>
</blockquote>
</li>

<li><p>Add a new paragraph after the class synopsis in 20.5.3 [tuple.tuple]:</p>
<blockquote>
<p>
<ins>-?- The destructor of <tt>tuple</tt> shall be a trivial destructor if 
<tt>(is_trivially_destructible_v&lt;Types&gt; &amp;&amp; ...)</tt> is <tt>true</tt>.</ins>
</p>
</blockquote>
</li>
</ol>



</body>
</html>
