<!doctype html public "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

<head>

<title>char8_t backward compatibility remediation</title>

<link rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

<style type="text/css">
pre {
    display: inline;
}

table#header th,
table#header td
{
    text-align: left;
}
table#references th,
table#references td
{
    vertical-align: top;
}

ins, ins * { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
del, del * { text-decoration:line-through; background-color:#FFA0A0 }
#hidedel:checked ~ * del, #hidedel:checked ~ * del * { display:none; visibility:hidden }

blockquote
{
    color: #000000;
    background-color: #F1F1F1;
    border: 1px solid #D1D1D1;
    padding-left: 0.5em;
    padding-right: 0.5em;
}
blockquote.stdins
{
    text-decoration: underline;
    color: #000000;
    background-color: #C8FFC8;
    border: 1px solid #B3EBB3;
    padding: 0.5em;
}
blockquote.stddel
{
    text-decoration: line-through;
    color: #000000;
    background-color: #FFEBFF;
    border: 1px solid #ECD7EC;
    padding-left: 0.5empadding-right: 0.5em;
}
</style>

</head>


<body>

<table id="header">
  <tr>
    <th>Document Number:</th>
    <td>PXXXXR0 <em>Draft</em></td>
  </tr>
  <tr>
    <th>Date:</th>
    <td>2018-12-05</td>
  </tr>
  <tr>
    <th>Audience:</th>
    <td>Library Evolution Working Group</td>
  </tr>
  <tr>
    <th>Reply-to:</th>
    <td>Tom Honermann &lt;tom@honermann.net&gt;</td>
  </tr>
</table>

<h1>char8_t backward compatibility remediation</h1>

<ul>
  <li><a href="#introduction">
      Introduction</a></li>
  <li><a href="#examples">
      Examples</a></li>
  <li><a href="#proposal">
      Proposal</a></li>
  <li><a href="#remediation">
      Remediation strategies</a>
    <ul>
      <li><a href="#shutdown">
          Shut this off, shut these all off</a></li>
      <li><a href="#keyword">
          New keyword and <tt>std</tt> members</a></li>
      <li><a href="#path_member_fns">
          Changed return type for <tt>std::filesystem::path</tt> member functions</a></li>
      <li><a href="#literal">
          UTF-8 literal remediation</a>
        <ul>
          <li><a href="#simple">
              Simple remediation for common scenarios</a></li>
          <li><a href="#complex">
              Complex remediation for uncommon scenarios</a></li>
          <li><a href="#array-init">
              Array initialization</a></li>
        </ul>
      </li>
    </ul>
  </li>
  <li><a href="#wording">
      Formal wording</a>
    <ul>
      <li><a href="#library_wording">
          Library wording</a></li>
      <li><a href="#annex_c_wording">
          Annex C Compatibility wording</a></li>
      <li><a href="#annex_d_wording">
          Annex D Compatibility features wording</a></li>
    </ul>
  </li>
  <li><a href="#references">
      References</a></li>
</ul>


<h1 id="introduction">Introduction</h1>

<p>The support for <tt>char8_t</tt> as adopted for C++20 via
<a title="char8_t: A type for UTF-8 characters and strings (Revision 6)"
   href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6.html">
P0482R6</a>
<sup><a title="char8_t: A type for UTF-8 characters and strings (Revision 6)"
        href="#ref_p0482r6">
[P0482R6]</a></sup> affects backward
compatibility for existing programs in at least the following ways:
<ul>
  <li>Introduction of a new <tt>char8_t</tt> keyword.</li>
  <li>Change of type for <tt>u8</tt> character and string literals.</li>
  <li>Introduction of new
      <tt>std::u8string</tt>,
      <tt>std::u8string_view</tt>,
      <tt>std::u8streampos</tt> type aliases and
      <tt>std::mbrtoc8</tt> and
      <tt>std::c8rtomb</tt> functions; these names may conflict with existing
      uses of these names due to ADL or use of <tt>using namespace std</tt>.
  </li>
  <li>Change of return type for <tt>std::filesystem::path</tt> member functions
      <tt>u8string</tt> and <tt>generic_u8string</tt>.
  </li>
</ul>
</p>

<p>This paper presents a set of remediation strategies for addressing backward
compatibility issues as well as a few minor changes to the C++ standard to
better facilitate migration to C++20.
</p>


<h1 id="examples">Examples</h1>

<p>
<table border="1">
  <tr>
    <th>Code</th>
    <th>C++17</th>
    <th>C++20 with P0482R6</th>
    <th>C++20 with this proposal</th>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">std::cout &lt;&lt; u8'x';
std::cout &lt;&lt; u8"text";</code></pre>
      </fieldset>
    </td>
    <td>Writes a sequence of UTF-8 code units as characters.<br/>
        (mojibake if the execution character encoding is not UTF-8)
    </td>
    <td>Writes an integer or pointer value.<br/>
        (consistent with handling of char16_t and char32_t literals)
    </td>
    <td>Ill-formed.<br/>
        (for all of char8_t, char16_t, and char32_t literals)
    </td>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">std::string s(u8"text");</code></pre>
      </fieldset>
    </td>
    <td>Constructs a string object with UTF-8 encoded data.</td>
    <td>Ill-formed.</td>
    <td>Ill-formed.</td>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">std::filesystem::path p = ...;
std::string s = p.u8string();</code></pre>
      </fieldset>
    </td>
    <td>Constructs a string object with UTF-8 encoded data.</td>
    <td>Ill-formed.</td>
    <td>Ill-formed.</td>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">std::filesystem::path(u8"filename");</code></pre>
      </fieldset>
    </td>
    <td>Constructs a path object with a UTF-8 filename.</td>
    <td>Ill-formed.</td>
    <td>Constructs a path object with a UTF-8 filename.</td>
  </tr>
</table>
</p>


<h1 id="proposal">Proposal</h1>

<ul>
  <li>Add deleted overloads of
      <tt>basic_ostream&lt;char, ...&gt;::operator&lt;&lt;</tt> for
      <tt>char8_t</tt> character and string types.  This avoids the silent
      and surprising behavior change introduced by
      <a title="char8_t: A type for UTF-8 characters and strings (Revision 6)"
         href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6.html">
      P0482R6</a>
      <sup><a title="char8_t: A type for UTF-8 characters and strings (Revision 6)"
              href="#ref_p0482r6">
      [P0482R6]</a></sup> that resulted in UTF-8 character being formatted as
      numeric values and UTF-8 strings being formatted as pointers.</li>
  <li>Add deleted overloads of
      <tt>basic_ostream&lt;char, ...&gt;::operator&lt;&lt;</tt> for
      <tt>char16_t</tt> and <tt>char32_t</tt> character and string types.  This
      removes surprising behavior that has been present since C++11; that
      characters are formatted as numeric values and that strings are formatted
      as pointers.</li>
  <li>Modify <tt>std::filesystem::u8path</tt> to accept ranges and iterators
      with <tt>char8_t</tt> value types.  This allows existing code that passes
      UTF-8 string literals to remain well-formed.<br/>
      <tt>u8path(u8"filename"); // Ok; ill-formed following
      <a title="char8_t: A type for UTF-8 characters and strings (Revision 6)"
         href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6.html">
      P0482R6</a>
      <sup><a title="char8_t: A type for UTF-8 characters and strings (Revision 6)"
              href="#ref_p0482r6">
      [P0482R6]</a></sup>.</tt></li>
  <li>Update the <tt>__cpp_lib_char8_t</tt> feature test macro to reflect
      proposed changes in library behavior.</li>
</ul>


<h1 id="remediation">Remediation strategies</h1>

<p>A single aproach to addressing backward compatibility impact is unlikely to
be the best approach for all projects.  This section presents a number of
options to address various types of backward compatibility impact.  In some
cases, the best solution may involve a mix of these options.
</p>


<h2 id="shutdown">Shut this off, shut these all off</h2>

<p>The simplest possible solution in the short term is to simply disable the
new features completely.  Clang and gcc will allow disabling <tt>char8_t</tt>
features in both the language and standard library, via a <tt>-fno-char8_t</tt>
option.  It is expected that Microsoft and EDG based compilers will offer a
similar option.
</p>

<p>This option should be considered a short-term solution to enable testing
existing C++17 code compiled as C++20 with minimal effort.  This isn't a
viable long-term option as continued use would complicate interoperation with
code that depends on the new features.
</p>


<h2 id="keyword">New keyword and <tt>std</tt> members</h2>

<p>The lack of a standard <tt>char8_t</tt> type has prompted some projects
to define their own <tt>char8_t</tt> type alias and corresponding
<tt>u8string</tt> type.  For open source projects reviewed by the author,
switching to the new standard features is straight forward at the
source level, though binary compatibility may be affected.  Such projects can
retain binary compatibility by continuing to use a type alias, but with a
name other than <tt>char8_t</tt>.
</p>


<h2 id="path_member_fns">Changed return type for <tt>std::filesystem::path</tt> member functions</h2>

<p><span style="background-color:#FFA0A0">FIXME</span>
</p>

<h2 id="literal">UTF-8 literals remediation</h2>

<p>Each of these strategies assumes a requirement for continued use of UTF-8
encoded literals with <tt>char</tt> based types.  For most projects, such a
requirement is expected to be temporary while the project is fully migrated to
C++20.  However, some projects may retain a sustained need for such literals.
For those projects, the <a href="#complex">complex remediation</a> approach
provides a long-term solution.
</p>


<h3 id="simple">Simple remediation for common scenarios</h3>

<p>Common uses of <tt>u8</tt> literals can be handled in a backward compatible
manner through use of <tt>reinterpret_cast</tt> or by adding new function
overloads.  Note that use of <tt>reinterpret_cast</tt> is ok in these situations
since <a href="http://eel.is/c++draft/expr#basic.lval-11">lvalues of type
<tt>char</tt> may be used to access values of other types</a>.
</p>

<p>This approach may suffice when there are just a few uses of UTF-8 literals
that need to be addressed.  In general, sprinkling <tt>reinterpret_cast</tt>
all over a code base is not desirable.
</p>

<table border="1">
  <tr>
    <th>Before</th>
    <th>After</th>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">const char &amp;r = u8’x';</code></pre>
      </fieldset>
    </td>
    <td>
      <fieldset><pre><code class="c++">const char &amp;r = <ins>reinterpret_cast&lt;const char &amp;&gt;(</ins>u8’x'<ins>)</ins>;</code></pre>
      </fieldset>
    </td>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">const char *p = u8"text";</code></pre>
      </fieldset>
    </td>
    <td>
      <fieldset><pre><code class="c++">const char *p = <ins>reinterpret_cast&lt;const char *&gt;(</ins>u8"text"<ins>)</ins>;</code></pre>
      </fieldset>
    </td>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">template&lt;int N&gt;
int ft(const char(&amp;)[N]);



ft(u8"text");</code></pre>
      </fieldset>
    </td>
    <td>
      <fieldset><pre><code class="c++">template&lt;int N&gt;
int ft(const char(&amp;)[N]);
<ins>template&lt;int N&gt;
int ft(const char8_t(&amp;)[N]);</ins>

ft(u8"text");</code></pre>
      </fieldset>
    </td>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">int operator ""_udl(const char*, unsigned long);


int v = u8"text"_udl;</code></pre>
      </fieldset>
    </td>
    <td>
      <fieldset><pre><code class="c++">int operator ""_udl(const char*, unsigned long);
<ins>int operator ""_udl(const char8_t*, unsigned long);</ins>

int v = u8"text"_udl;</code></pre>
      </fieldset>
    </td>
  </tr>
</table>


<h3 id="complex">Complex remediation for uncommon scenarios</h3>

<p>The techniques applied here also apply to the common scenerios discussed
in the prior section.  This approach makes use of P0732 to enable constexpr
UTF-8 encoded <tt>char</tt> based literals using a user defined literal.
The example code below defines overloaded character and string UDL operators
named <tt>_as_char</tt>.  These UDLs can then be used in place of existing
UTF-8 character and string literals.
</p>

<p>
<fieldset>
<pre><code class="c++">#include &lt;utility&gt;

template&lt;std::size_t N&gt;
struct char8_t_string_literal {
  static constexpr inline std::size_t size = N;
  template&lt;std::size_t... I&gt;
  constexpr char8_t_string_literal(
    const char8_t (&amp;r)[N],
    std::index_sequence&lt;I...&gt;)
  :
    s{r[I]...}
  {}
  constexpr char8_t_string_literal(
    const char8_t (&amp;r)[N])
  :
    char8_t_string_literal(r, std::make_index_sequence&lt;N&gt;())
  {}
  auto operator &lt;=&gt;(const char8_t_string_literal&amp;) = default;
  char8_t s[N];
};

template&lt;char8_t_string_literal L, std::size_t... I&gt;
constexpr inline const char as_char_buffer[sizeof...(I)] =
  { static_cast&lt;char&gt;(L.s[I])... };

template&lt;char8_t_string_literal L, std::size_t... I&gt;
constexpr auto&amp; make_as_char_buffer(std::index_sequence&lt;I...&gt;) {
  return as_char_buffer&lt;L, I...&gt;;
}

constexpr char operator ""_as_char(char8_t c) {
  return c;
}

template&lt;char8_t_string_literal L&gt;
constexpr auto&amp; operator""_as_char() {
  return make_as_char_buffer&lt;L&gt;(std::make_index_sequence&lt;decltype(L)::size&gt;());
}
</code></pre>
</fieldset>
</p>

<table border="1">
  <tr>
    <th>Before</th>
    <th>After</th>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">constexpr const char &amp;r = u8’x';</code></pre>
      </fieldset>
    </td>
    <td>
      <fieldset><pre><code class="c++">constexpr const char &amp;r = u8’x'<ins>_as_char</ins>;</code></pre>
      </fieldset>
    </td>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">constexpr const char *p = u8"text";</code></pre>
      </fieldset>
    </td>
    <td>
      <fieldset><pre><code class="c++">constexpr const char *p = u8"text"<ins>_as_char</ins>;</code></pre>
      </fieldset>
    </td>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">// gcc extension in C++17; standard C++ doesn't permit conversion
// to arrays of unknown bound.
constexpr const char (&amp;r)[] = u8"text";</code></pre>
      </fieldset>
    </td>
    <td>
      <fieldset><pre><code class="c++">// Ok in C++20 with <a title="Class Types in Non-Type Template Parameters" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0732r2.pdf">P0388R2</a> <sup><a title="Class Types in Non-Type Template Parameters" href="#ref_p0388r2">[P0388R2]</a></sup>

constexpr const char (&amp;r)[] = u8"text"<ins>_as_char</ins>;</code></pre>
      </fieldset>
    </td>
  </tr>
</table>

<p>When wrapped in macros, the above UDL can be used to retain source
compatibility across C++17 and C++20 for all known scenarios except for
array initialization.
<fieldset><pre><code class="c++">#include &lt;utility&gt;

#if defined(__cpp_char8_t)
#define U8(x) u8##x##_as_char
#else
#define U8(x) u8##x
#endif

constexpr char c = U8('x');
constexpr const char &amp;rc = U8('x');
constexpr const char *ps = U8("text");
constexpr const char (&amp;rac)[] = U8("text"); // Ok (with gcc extension or P0388).
</fieldset>
</p>


<h3 id="array-init">Array initialization</h3>

<table border="1">
  <tr>
    <th>Before</th>
    <th>After</th>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">char a[] = u8"text";</code></pre>
      </fieldset>
    </td>
    <td>
      <fieldset><pre><code class="c++"><span style="background-color:#FFA0A0">FIXME</span></code></pre>
      </fieldset>
    </td>
  </tr>
  <tr>
    <td>
      <fieldset><pre><code class="c++">constexpr char a[] = u8"text";</code></pre>
      </fieldset>
    </td>
    <td>
      <fieldset><pre><code class="c++"><span style="background-color:#FFA0A0">FIXME</span></code></pre>
      </fieldset>
    </td>
  </tr>
</table>


<h1 id="wording">Formal wording</h1>

<input type="checkbox" id="hidedel">Hide deleted text</input>

<p>These changes are relative to
<a title="Working Draft, Standard for Programming Language C++"
   href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4762.pdf">
N4762</a>
<sup><a title="Working Draft, Standard for Programming Language C++"
        href="#ref_n4762">
[N4762]</a></sup></p>


<h2 id="library_wording">Library wording</h2>

<p>Change in table 35 of
<a href="http://eel.is/c++draft/support.limits.general#3">
16.3.1 [support.limits.general] paragraph 3</a>:
<blockquote>
<div style="margin-left: 1em;">
<table>
  <tr>
    <td align="center">
      Table 35 &mdash; Standard library feature-test macros
    </td>
  </tr>
  <tr>
    <td align="center">
      <table border="1">
        <tr>
          <th align="center">Macro name</th>
          <th align="center">Value</th>
          <th align="center">Header(s)</th>
        </tr>
        <tr>
          <td>[&hellip;]</td>
          <td>[&hellip;]</td>
          <td>[&hellip;]</td>
        </tr>
        <tr>
          <td>__cpp_lib_char8_t</td>
          <td><del>201811</del><ins>201812L</ins> <strong><em style="background-color: yellow">** placeholder **</em></strong></td>
          <td>&lt;atomic&gt;
              &lt;filesystem&gt;
              &lt;istream&gt;
              &lt;limits&gt;
              &lt;locale&gt;
              &lt;ostream&gt;
              &lt;string&gt;
              &lt;string_view&gt;</td>
        </tr>
        <tr>
          <td>[&hellip;]</td>
          <td>[&hellip;]</td>
          <td>[&hellip;]</td>
        </tr>
      </table>
    </td>
  </tr>
</table>
</div>
</blockquote>
</p>

<p><em>Drafting note: the final value for the <tt>__cpp_lib_char8_t</tt> feature
test macro will be selected by the project editor to reflect the date of
approval.</em>
</p>

<p>Append new paragraphs in
<a href="http://eel.is/c++draft/ostream.inserters.character">
28.7.5.2.4 [ostream.inserters.character]</a>:
<blockquote class=stdins>
template&lt;class traits&gt;<br/>
&nbsp;&nbsp;basic_ostream&lt;char, traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;char, traits&gt;&amp; out, char8_t c) = delete;<br/>
template&lt;class traits&gt;<br/>
&nbsp;&nbsp;basic_ostream&lt;char, traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;char, traits&gt;&amp; out, char16_t c) = delete;<br/>
template&lt;class traits&gt;<br/>
&nbsp;&nbsp;basic_ostream&lt;char, traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;char, traits&gt;&amp; out, char32_t c) = delete;<br/>
</blockquote>
<blockquote class=stdins>
<em>6. [ Note:</em> These overloads prevent formatting character values as
numeric values.
<em>&mdash; end note ]</em>
</blockquote>
<blockquote class=stdins>
template&lt;class traits&gt;<br/>
&nbsp;&nbsp;basic_ostream&lt;char, traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;char, traits&gt;&amp; out, const char8_t* s) = delete;<br/>
template&lt;class traits&gt;<br/>
&nbsp;&nbsp;basic_ostream&lt;char, traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;char, traits&gt;&amp; out, const char16_t* s) = delete;<br/>
template&lt;class traits&gt;<br/>
&nbsp;&nbsp;basic_ostream&lt;char, traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;char, traits&gt;&amp; out, const char32_t* s) = delete;<br/>
</blockquote>
<blockquote class=stdins>
<em>7. [ Note:</em> These overloads prevent formatting strings as pointer
values.
<em>&mdash; end note ]</em>
</blockquote>
</p>


<h2 id="annex_c_wording">Annex C Compatibility wording</h2>

<p>Change in
<a href="http://eel.is/c++draft/diff.cpp17.input.output#2">
C.5.11 [diff.cpp17.input.output] paragraph 2</a>:
<blockquote>
<strong>Affected subclause:</strong> <a href="http://eel.is/c++draft/ostream.inserters.character">27.7.5.2.4</a><br/>
<strong>Change</strong>: Overload resolution for ostream inserters
used with UTF-8 literals.<br/>
<strong>Rationale</strong>: Required for new features.<br/>
<strong>Effect on original feature</strong>: Valid ISO C++ 2017 code that
passes UTF-8 literals to <tt>basic_ostream<ins>&lt;char, ...&gt;</ins>::operator&lt;&lt;</tt> <del>no
longer calls character related overloads</del><ins>is now ill-formed</ins>.
<br/>
<div style="margin-left: 1em;">
<tt>
<pre>std::cout &lt;&lt; u8"text";       <em>// Previously called operator&lt;&lt;(const char*) and printed a string.</em>
                             <em>// Now <del>calls operator&lt;&lt;(const void*) and prints a pointer value</del><ins>ill-formed</ins>.</em>
std::cout &lt;&lt; u8'X';          <em>// Previously called operator&lt;&lt;(char) and printed a character.</em>
                             <em>// Now <del>calls operator&lt;&lt;(int) and prints an integer value</del><ins>ill-formed</ins>.</em>
</pre>
</tt>
</div>
</blockquote>
</p>


<p>Add a new paragraph after
<a href="http://eel.is/c++draft/diff.cpp17.input.output#2">
C.5.11 [diff.cpp17.input.output] paragraph 2</a>:
<blockquote class="stdins">
<strong>Affected subclause:</strong> <a href="http://eel.is/c++draft/ostream.inserters.character">27.7.5.2.4</a><br/>
<strong>Change</strong>: Overload resolution for ostream inserters
used with <tt>char16_t</tt> and <tt>char32_t</tt> types.<br/>
<strong>Rationale</strong>: Removal of surprising behavior.<br/>
<strong>Effect on original feature</strong>: Valid ISO C++ 2017 code that
passes <tt>char16_t</tt> and <tt>char32_t</tt> characters or strings to
<tt>basic_ostream&lt;char, ...&gt;::operator&lt;&lt;</tt> is now ill-formed.
<br/>
<div style="margin-left: 1em;">
<tt>
<pre>std::cout &lt;&lt; u"text";        <em>// Previously called operator&lt;&lt;(const void*) and printed a pointer value.</em>
                             <em>// Now ill-formed.</em>
std::cout &lt;&lt; u'X';           <em>// Previously called operator&lt;&lt;(int) and printed an integer value.</em>
                             <em>// Now ill-formed.</em>
</pre>
</tt>
</div>
</blockquote>
</p>


<h2 id="annex_d_wording">Annex D Compatibility features wording</h2>

<p>Change in
<a href="http://eel.is/c++draft/depr.fs.path.factory#1">
D.16 [depr.fs.path.factory] paragraph 1</a>:
<blockquote>
<em>Requires:</em> The <tt>source</tt> and <tt>[first, last)</tt> sequences are
UTF-8 encoded.  The value type of <tt>Source</tt> and <tt>InputIterator</tt> is
<tt>char</tt><ins> or <tt>char8_t</tt></ins>.  <tt>Source</tt> meets the
requirements specified in
<a href="http://eel.is/c++draft/fs.path.req">27.11.7.3</a>.
</blockquote>
</p>




<h1 id="references">References</h1>

<table id="references">
  <tr>
    <td id="ref_n4762"><sup>[N4762]</sup></td>
    <td>
      "Working Draft, Standard for Programming Language C++", N4762, 2018.<br/>
      <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4762.pdf">
      http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4762.pdf</a></td>
  </tr>
  <tr>
    <td id="ref_p0388r2"><sup>[P0388R2]</sup></td>
    <td>
      Robert Haberlach,
      "Permit conversions to arrays of unknown bound", P0388R2, 2018.<br/>
      <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0388r2.html">
      http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0388r2.html</a></td>
  </tr>
  <tr>
    <td id="ref_p0482r6"><sup>[P0482R6]</sup></td>
    <td>
      Tom Honermann,
      "char8_t: A type for UTF-8 characters and strings (Revision 6)", P0482R6, 2018.<br/>
      <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6.html">
      http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6.html</a></td>
  </tr>
  <tr>
    <td id="ref_p0732r2"><sup>[P0732R2]</sup></td>
    <td>
      Jeff Snyder and Louis Dionne,
      "Class Types in Non-Type Template Parameters", P0732R2, 2018.<br/>
      <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0732r2.pdf">
      http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0732r2.pdf</a></td>
  </tr>
</table>

</body>