<html>

<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF8">

  <meta name="description" content="Proposal for C++ Standard">
  <meta name="keywords" content="C++,cplusplus,wg21">
  <meta name="author" content="Alisdair Meredith">

  <title>Reviewing Deprecated Facilities of C++20 for C++23</title>

  <style type="text/css">
    ins {background-color:#A0FFA0}
    del {background-color:#FFA0A0}
    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;
    }
    blockquote.recommend
    {
      background-color:#ffffb0;
      padding-left: 10px;
      padding-right: 10px;
      padding-top: 1px;
      padding-bottom: 1px;
    }
    blockquote.review
    {
      background-color:#b0ffb0;
      padding-left: 10px;
      padding-right: 10px;
      padding-top: 1px;
      padding-bottom: 1px;
    }
    blockquote.review_note
    {
      background-color:#ffffcc;
      padding-left: 15px;
      padding-right: 15px;
      padding-top: 1px;
      padding-bottom: 1px;
    }
    blockquote.draft_wording
    {
      background-color:#f8f8f8;
      padding-left: 15px;
      padding-right: 15px;
      padding-top: 1px;
      padding-bottom: 1px;
    }
    tr:nth-child(even) {background-color: #f2f2f2;}
  </style>
</head>

<body>
<table>
<tr>
  <td align="left">Doc. no.</td>
  <td align="left">P2139R0</td>
</tr>
<tr>
  <td align="left">Date:</td>
  <td align="left">2020-03-13</td>
</tr>
<tr>
  <td align="left">Project:</td>
  <td align="left">Programming Language C++</td>
</tr>
<tr>
  <td align="left">Audience:</td>
  <td align="left">Evolution Working Group Incubator</td>
</tr><tr>
  <td align="left"></td>
  <td align="left">Library Evolution Working Group Incubator</td>
</tr>
<tr>
  <td align="left">Reply to:</td>
  <td align="left">Alisdair Meredith &lt;<a href="mailto:ameredith1@bloomberg.net">ameredith1@bloomberg.net</a>&gt;</td>
</tr>
</table>

<h1>Reviewing Deprecated Facilities of C++20 for C++23</h1>

<h2>Table of Contents</h2>
<ol start="0">
<li><a href="#rev.hist">Revision History</a></li>
  <ul>
  <li><a href="#rev.1">Revision 1</a></li>
  <li><a href="#rev.0">Revision 0</a></li>
  </ul>
<li><a href="#1.0">Abstract</a></li>
<li><a href="#2.0">Stating the problem</a></li>
<li><a href="#3.0">Propose Solution</a></li>
  <ul>
  <li><a href="#3.1">D.1 Arithmetic conversion on enumerations [depr.arith.conv.enum]</a></li>
  <li><a href="#3.2">D.2 Implicit capture of <tt>*this</tt> by reference [depr.capture.this]</a></li>
  <li><a href="#3.3">D.3 Comma operator in subscript expressions [depr.comma.subscript]</a></li>
  <li><a href="#3.4">D.4 Array comparisons [depr.array.comp]</a></li>
  <li><a href="#3.5">D.5 Deprecated volatile types [depr.volatile.type]</a></li>
  <li><a href="#3.6">D.6 Redeclaration of static constexpr data members [depr.static_constexpr]</a></li>
  <li><a href="#3.7">D.7 Non-local use of TU-local entities [depr.local]</a></li>
  <li><a href="#3.8">D.8 Implicit declaration of copy functions [depr.impldec]</a></li>
  <li><a href="#3.9">D.9 C headers [depr.c.headers]</a></li>
  <li><a href="#3.10">D.10 Requires paragraph [depr.res.on.required]</a></li>
  <li><a href="#3.11">D.11 Relational operators [depr.relops]</a></li>
  <li><a href="#3.12">D.12 <tt>char*</tt> streams [depr.str.strstreams]</a></li>
  <li><a href="#3.13">D.13 Deprecated type traits [depr.meta.types]</a></li>
  <li><a href="#3.14">D.14 Tuple [depr.tuple]</a></li>
  <li><a href="#3.15">D.15 Variant [depr.variant]</a></li>
  <li><a href="#3.16">D.16 Deprecated iterator primitives [depr.iterator.primitives]</a></li>
  <li><a href="#3.17">D.17 Deprecated <tt>move_iterator</tt> access [depr.move.iter.elem]</a></li>
  <li><a href="#3.18">D.18 Deprecated <tt>shared_ptr</tt> atomic access [depr.util.smartptr.shared.atomic]</a></li>
  <li><a href="#3.19">D.19 Deprecated <tt>basic_string</tt> capacity [depr.string.capacity]</a></li>
  <li><a href="#3.20">D.20 Deprecated Standard code conversion facets [depr.locale.stdcvt]</a></li>
  <li><a href="#3.21">D.21 Deprecated convience conversion interfaces [depr.conversions]</a></li>
  <li><a href="#3.22">D.22 Deprecated locale category facets [depr.locale.category]</a></li>
  <li><a href="#3.23">D.23 Deprecated filesystem path factory functions [depr.fs.path.factory]</a></li>
  <li><a href="#3.24">D.24 Deprecated atomic operations [depr.atomics]</a></li>
  </ul>
<li><a href="#4.0">Other Directions</a></li>
<li><a href="#5.0">Formal Wording</a></li>
<li><a href="#6.0">Acknowledgements</a></li>
<li><a href="#7.0">References</a></li>
</ol>


<h2><a name="rev.hist">Revision History</a></h2>

<h3><a name="rev.0">Revision 0</a></h3>
<p>
Original version of the paper for the 2020 post-Prague mailing.
</p>


<h2><a name="1.0">1 Abstract</a></h2>
<p>
This paper evaluates all the existing deprecated facilities in the C++20
standard, and recommends removing a subset from Annex D in C++23, either by
removing from the standard entirely, or by undeprecating and restoring to the
main text.
</p>


<h2><a name="2.0">2 Stating the problem</a></h2>
<p>
With the release of a new C++ standard, we get an opportunity to revisit the
features identified for deprecation, and consider if we are prepared to clear
any out yet, either by removing completely from the standard, or by reversing
the deprecation decision and restoring the feature to full service.  This paper
makes no attempt to offer proposals for removing features other than those
deprecated in Annex D, nor does it attempt to identify new candidates for
deprecation.
</p>
<p>
In an ideal world, the start of every release cycle would cleanse the list of
deprecated features entirely, allowing the language and library to evolve
cleanly without holding too much deadweight.  This paper is an attempt to
consolidate all likely requests (and papers) to review isolated features on
Annex D, and gain efficiency by performing one consolidated review.  In
practice, C++ has some long-term deprecated facilities that are difficult to
remove, and equally difficult to rehabilitate.  It seems reasonable that work
could be split into follow-up papers if a direction has appeal, but needs more
work for consensus to advance; one possible goal of this paper is to discover
which features we may be interested in following up while maintaining the tempo
of an efficient high level review.
</p>
<p>
The benefits of making the choice to remove features early in a standard cycle
is that we will get the most experience we can from the bleeding-edge adopters
whether a particular removal is more problematic than expected - but even this
data point is limited, as bleeding-edge adopters typically have less reliance
on deprecated features, eagerly adopting the newer replacement facilities.
</p>
<p>
However, do note that with the three year release cadence for the C++ standard,
we will often be re-evaluating features whose deprecated status has barely
reached print.
</p>
<p>
We have precedent that Core language features are good targets for removal,
typically taking two standard cycles to remove a deprecated feature, although
often prepared to entirely remove a feature even without a period of
deprecation, if the cause is strong enough.
</p>
<p>
The library experience has been mixed, with no desire to remove anything
without a period of deprecation (other than <tt>gets</tt>) and no precedent
prior to C++17 for actually removing deprecated features.
</p>
<p>
The precedent set for the library in C++17 seems to be keener to clear out the
old code more quickly though, even removing features deprecated as recently as
the previous standard, with the ink still drying on the text!  Accordingly,
this paper will be fairly aggressive in its attempt to clear out old libraries.
This is perhaps more reasonable for the library clauses than the core language,
as the Zombie Names clause, <b>16.5.4.3.1 [zombie.names]</b> allows vendors to
continue shipping features long after they have left the standard, as long as
their existing customers rely on them.
</p>

<h2><a name="3.0">3 Proposed Solution</a></h2>
<p>
We will review each deprecated facility, and make a strong and a weak
recommendation.  The strong recommendation is the preferred direction of the
authors, who lean towards early removal.  There will also be a weak
recommendation, which is an alternative proposal for the evolution groups to
consider, if the strong recommendation does not find favor.  Finally, wording
is generally provided for both the strong and weak recommendations, which will
be collated into a unified Proposed Wording section once the various
recommendations have been given direction by the corresponding evolution group.
</p>
<p>
All proposed wording is relative to the expected C++20 DIS, including the
revised clause numbers.  However, it will be updated to properly reflect the
final document in the pre-Varna mailing, incorporating any feedback accrued
in the meantime.
</p>

<p>
Checklist for recommendations:
</p>
<table>
  <tr>
    <td><b>Subclause</b></td>
    <td><b>Introduced</b></td>
    <td><b>Deprecated</b></td>
    <td><b>Paper</b></td>
    <td><b>Feature</b></td>
    <td><b>Strong Recommendation</b></td>
    <td><b>Weak Recommendation</b></td>
    <td><b>Incubator Recommendation</b></td>
    <td><b>Evolution Recommendation</b></td>
    <td>Action</td>
  </tr>

  <tr>
    <td>D.1</td>
    <td>C++98</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1120r0">P1120R0</a></td>
    <td>Arithmetic conversion on enumerations</td>
    <td>No action</td>
    <td>Remove now</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.2</td>
    <td>C++11</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0806r2">P0806R2</a></td>
    <td>Implicit capture of <tt>*this</tt> by reference</td>
    <td>Remove now</td>
    <td>No action</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.3</td>
    <td>C++98</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1161r3">P1161R3</a></td>
    <td>Comma operator in subscript expressions</td>
    <td>No action</td>
    <td>Needs paper</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.4</td>
    <td>C++98</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1120r0">P1120R0</a></td>
    <td>Array comparisons</td>
    <td>Remove now</td>
    <td>No action</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.5</td>
    <td>C++98</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1152r4">P1152R4</a></td>
    <td>Deprecated use of <tt>volatile</tt></td>
    <td>No action</td>
    <td>Remove now</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.6</td>
    <td>C++11</td>
    <td>C++17</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0386r2">P0386R2</a></td>
    <td>Reclare <tt>constexpr</tt> members</td>
    <td>No action</td>
    <td>Remove now</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.7</td>
    <td>C++98</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1815r2">P1815R2</a></td>
    <td>Non-local use of TU-local entities</td>
    <td>No action</td>
    <td>No action yet</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.8</td>
    <td>C++98</td>
    <td>C++11</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3203">N3203</a></td>
    <td>Implicit special members</td>
    <td>Remove on copy<br/>Undeprecate on dtor</td>
    <td>No action yet</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.9</td>
    <td>C++98</td>
    <td>C++98</td>
    <td></td>
    <td>C <tt>&lt;*.h&gt;</tt> headers</td>
    <td>Undeprecate</td>
    <td>Remove now</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.10</td>
    <td>C++98</td>
    <td>C++20</td>
    <td></td>
    <td><i>Requires:</i> clauses</td>
    <td>Remove now</td>
    <td>No action</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.11</td>
    <td>C++98</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0768r1">P0768R1</a></td>
    <td><tt>relops</tt></td>
    <td>Remove now</td>
    <td>Fix mandates</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.12</td>
    <td>C++98</td>
    <td>C++98</td>
    <td></td>
    <td><tt>char *</tt> streams</td>
    <td>No action</td>
    <td>No action yet</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.13</td>
    <td>C++11</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0767r1">P0767R1</a></td>
    <td>Deprecated type traits</td>
    <td>Fix mandates</td>
    <td>Remove now</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.14</td>
    <td>C++11</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1831r1">P1831R1</a></td>
    <td><tt>volatile tuple</tt> API</td>
    <td>No action</td>
    <td>No action</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.15</td>
    <td>C++17</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1831r1">P1831R1</a></td>
    <td><tt>volatile variant</tt> API</td>
    <td>Remove now</td>
    <td>No action</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.16</td>
    <td>C++98</td>
    <td>C++17</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0174r0">P0174R2</a></td>
    <td><tt>std::iterator</tt></td>
    <td>Remove now</td>
    <td>Undeprecate</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.17</td>
    <td>C++11</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1252r2">P1252R2</a></td>
    <td><tt>move_iterator::operator-&gt;</tt></td>
    <td>No action</td>
    <td>Remove now</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.18</td>
    <td>C++11</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0718r2">P0718R2</a></td>
    <td>C API to use <tt>shared_ptr</tt> atomically</td>
    <td>Remove now</td>
    <td>Fix mandates</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.19</td>
    <td>C++98</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0966r1">P0966R1</a></td>
    <td><tt>basic_string::reserve()</tt></td>
    <td>No action</td>
    <td>Remove now</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.20</td>
    <td>C++11</td>
    <td>C++17</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0">P0618R0</a></td>
    <td><tt>&lt;codecvt&gt;</tt></td>
    <td>Remove now</td>
    <td>No action yet</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.21</td>
    <td>C++11</td>
    <td>C++17</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0">P0618R0</a></td>
    <td><tt>wstring_convert</tt> et al.</td>
    <td>Remove now</td>
    <td>Fix mandates</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.22</td>
    <td>C++11</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6">P0482R6</a></td>
    <td>Deprecated locale category facets</td>
    <td>No action</td>
    <td>No action</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.23</td>
    <td>C++17</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6">P0482R6</a></td>
    <td><tt>filesystem::u8path</tt></td>
    <td>Fix mandates</td>
    <td>Remove now</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
  <tr>
    <td>D.24</td>
    <td>C++11</td>
    <td>C++20</td>
    <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0883r2">P0883R2</a></td>
    <td>atomic operations</td>
    <td>No action</td>
    <td>Partially Remove</td>
    <td>pending...</td>
    <td>pending...</td>
  </tr>
 </table>

 <p>
 One sign of the success we have had with previous papers is that roughly
 70% of the subclauses in Annex D were added in the latest C++20 standard,
 and only one feature remains that was deprecated by the C++11 standard.
 Notably, that is the last remaining core feature that was deprecated prior
 to C++20.
 </p>

<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.1">D.1 Arithmetic conversion on enumerations [depr.arith.conv.enum]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This feature was deprecated as part of the effort to make the new
spaceship operator <i>do the right thing</i>, adopted by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1120r0">P1120R0</a>.
It potentially impacts on code written against C++98 and later standards.
</p>

<p>
With the introduction of the 3-way comparison &quot;spaceship&quot;
operator, there was a concern to avoid some implicit comparisons that
might be lossy (due to rounding of floating point values) or giving up
intended type safety (by using enums rather than integer types to
indicate more than just a value).  While the 3-way comparison operator
is specified to reject such comparisons, the existing comparison
operators were granted ongoing compatibility in these cases, but
deprecated.  It is likely that most, but not all, such usage relying
on implicit conversion is a latent bug, and all such code would be
clearer to folks reading the code if the implicit conversions were
made explicit.
</p>

<p>
While we would like to recommend the removal of these deprecated
comparisons, bringing all the comparison operators into harmony for
which types they interoperate on, the case for all uses being latent
bugs is not as strong as for array comparisons (D.4), therefore it
seems reasonable to allow another standard cycle encouraging compilers
to issue deprecation warnings so that users can clean up their code.
Hence, the strong recommendation is to do nothing for C++23, and
strongly reconsider for C++26.  The weak recommendation is to take
decisive action and remove now, harmonizing the comparison operators.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
Take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Remove this feature from C++23
</blockquote>

<blockquote class="draft_wording">
<h4>7.4 Usual arithmetic conversions [expr.arith.conv]</h4>
<ol>
<li>
Many binary operators that expect operands of arithmetic or enumeration type
cause conversions and yield result types in a similar way. The purpose is to
yield a common type, which is also the type of the result. This pattern is
called the <i>usual arithmetic conversions</i>, which are defined as follows:
  <ol>
  <li>
&mdash; If either operand is of scoped enumeration type (9.7.1), no conversions
are performed; if the other operand does not have the same type, the expression
is ill-formed.
  </li>
  <li><ins>
&mdash; If either operand is of unscoped enumeration type (9.7.1), and the
other operand  is of a different enumeration type or a floating-point type, 
the expression is ill-formed.
  </ins></li>
  <li>
&mdash; If either operand is of type <tt>long double</tt>, the other shall be converted
to <tt>long double</tt>.
  </li>
  <li>
&mdash; Otherwise, if either operand is <tt>double</tt>, the other shall be converted to
<tt>double</tt>.
  </li>
  <li>
&mdash; Otherwise, if either operand is <tt>float</tt>, the other shall be converted to
<tt>float</tt>.
  </li>
  <li>
&mdash; Otherwise, the integral promotions (7.3.6) shall be performed on both
operands.<sup>57</sup> Then the following rules shall be applied to the
promoted operands:
    <ol>
    <li>
&mdash; If both operands have the same type, no further conversion is needed.
    </li>
    <li>
&mdash; Otherwise, if both operands have signed integer types or both have
unsigned integer types, the operand with the type of lesser integer conversion
rank shall be converted to the type of the operand with greater rank.
    </li>
    <li>
&mdash; Otherwise, if the operand that has unsigned integer type has rank
greater than or equal to the rank of the type of the other operand, the operand
with signed integer type shall be converted to the type of the operand with
unsigned integer type.
    </li>
    <li>
&mdash; Otherwise, if the type of the operand with signed integer type can
represent all of the values of the type of the operand with unsigned integer
type, the operand with unsigned integer type shall be converted to the type of
the operand with signed integer type.
    </li>
    <li>
&mdash; Otherwise, both operands shall be converted to the unsigned integer
type corresponding to the type of the operand with signed integer type.
    </li>
    </ol>
  </li>
  </ol>
</li>
<li><del>
If one operand is of enumeration type and the other operand is of a different
enumeration type or a floating-point type, this behavior is deprecated (D.1).
</del></li>
</ol>

<h4><del>D.1 Arithmetic conversion on enumerations [depr.arith.conv.enum]</del></h4>
<ol>
<li>
<del>The ability to apply the usual arithmetic conversions (7.4) on operands where
one is of enumeration type and the other is of a different enumeration type or
a floating-point type is deprecated. [Note: Three-way comparisons (7.6.8)
between such operands are ill-formed. <i>&mdash;end note</i>] [<i>Example:</i></del>
<blockquote><pre>
<del>enum E1 { e };</del>
<del>enum E2 { f };</del>
<del>bool b = e &lt;= 3.7;                // deprecated</del>
<del>int k = f - e;                    // deprecated</del>
<del>auto cmp = e &lt;=> f;               // error</del>
</pre></blockquote>
<del><i>&mdash;end example</i>]</del>
</li>
</ol>
</blockquote>

<blockquote class="note">
We do not anticipate any impact on library wording by this removal.
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="review">
<b>EWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.2">D.2 Implicit capture of <tt>*this</tt> by reference [depr.capture.this]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This feature was deprecated in C++20 by
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0806r2">P0806R2</a>.
Its removal would potentially impact on programs written against C++11 or a
later standard.
</p>
<p>
The concern addressed by the paper is that the implicit capture of <tt>this</tt>
as a <i>reference</i> to data members on a default-capture that copies is
surprising and often misleading.  C++20 introduced the explicit capture of
<tt>this</tt> as a pointer, or <tt>*this</tt> by value, to clearly disambiguate
the different use cases.  However, as the syntax to migrate to was introduced
only in C++20, there was a clear desire for at least one standard retaining the
implicit capture support as deprecated while users migrate their code at a time
of their own choosing.
</p>
<p>
In the interest of clear code and fewer bugs from the surprising implicit
defaults, the strong recommendation of this paper is to complete the work
started in P0806 and remove the implicit capture from C++23.  The weak
recommendation is to retain deprecated support for another three years, and
strongly reconsider removal in C++26.  There is no suggestion to undeprecate.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
Remove this feature from C++23
</blockquote>

<blockquote class="note">
Draft core wording to enforce the removal (simply removing the deprecation
notice is not enough).
</blockquote>

<blockquote class="draft_wording">
<h4><del>D.2 Implicit capture of <tt>*this</tt> by reference[depr.capture.this]</del></h4>
<ol>
<li>
<del>For compatibility with prior C++ International Standards, a
<i>lambda-expression</i> with <i>capture-default</i> <tt>=</tt> (7.5.5.2) may
implicitly capture <tt>*this</tt> by reference. [<i>Example:</i></del>
<blockquote><pre>
<del>struct X {</del>
  <del>int x;</del>
  <del>void foo(int n) {</del>
    <del>auto f = [=]() { x = n; };        // deprecated: x means this-&gt;x, not a copy thereof</del>
    <del>auto g = [=, this]() { x = n; };  // recommended replacement</del>
  <del>}</del>
<del>};</del>
</pre></blockquote>
<del><i>&mdash;end example</i>]</del>
</li>
</ol>
</blockquote>

<blockquote class="note">
We do not anticipate any impact on library wording by this removal.
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Take no action yet, strongly reconsider removal in C++26.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="review">
<b>EWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.3">D.3 Comma operator in subscript expressions [depr.comma.subscript]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This feature was deprecated for C++20 by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1161r3">P1161R3</a>
to allow for a future extension in the language to support a simpler syntax for
multiple-dimension arrays.  Its removal would impact on code written against the
C++98 and later standards, and potentially interoperating with C language headers.
</p>

<p>
There is no value in removing this deprecated feature without also adding the
extension for multiple-dimension arrays, which goes beyond the scope of this
simpler review paper.  As such, the strong recommendation is to do nothing with
this feature as part of the overall review.  The weak recommendation is to
commission a follow-up paper to facilitate removal by proposing the full extension.
We do not consider undeprecation appropriate at this time.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
Take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Commission a paper to propose a simpler syntax for multi-dimensional arrays.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>

<!--- block comment to remove code ---
<blockquote class="draft_wording">	
<h4>7.6.20 Comma operator [expr.comma]</h4>
<ol start="3">
<li><del>
[<i>Note:</i> A comma expression (7.6.20) appearing as the
<i>expr-or-braced-init-list</i> of a subscripting expression is deprecated; see
D.3. <i>&mdash;end note</i>]
</del></li>
</ol>

<h4>7.6.1.1 Subscripting [expr.sub]</h4>
<ol start="2">
<li><del>
[<i>Note:</i> A comma expression (7.6.20) appearing as the
<i>expr-or-braced-init-list</i> of a subscripting expression is deprecated; see
D.3. <i>&mdash;end note</i>]
</del></li>
</ol>

<h4><del>D.3 Comma operator in subscript expressions [depr.comma.subscript]</del></h4>
<ol>
<li>
<del>A comma expression (7.6.20) appearing as the <i>expr-or-braced-init-list</i>
of a subscripting expression (7.6.1.1) is deprecated. [<i>Note:</i> A
parenthesized comma expression is not deprecated. <i>&mdash;end note</i>]
[<i>Example:</i></del>
<blockquote><pre>
<del>void f(int *a, int b, int c) {</del>
      <del>a[b,c];                     // deprecated</del>
      <del>a[(b,c)];                   // OK</del>
<del>}</del>
</pre></blockquote>
<del><i>&mdash;end example</i>]</del>
</li>
</ol>
</blockquote>

<blockquote class="note">
We do not anticipate any impact on library wording by this removal.
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>
--- end of block comment to remove code -->

<blockquote class="review">
<b>EWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.4">D.4 Array comparisons [depr.array.comp]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This feature was deprecated as part of the effort to make the new spaceship
operator <i>do the right thing</i>, adopted by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1120r0">P1120R0</a>.
It potentially impacts on code written against C++98 and later standards.
</p>

<p>
The deprecated comparison operator for arrays was not so much a deliberately
designed feature, but accidental oversight that array-to-pointer decay would
kick in, and so we compare whether two arrays are literally the same array at
the same address, rather than whether two distinct arrays have the same
contents.  Identity tests are typically performed by explicitly taking the
address of the objects we wish to validate; it would be highly unusual to rely
on an implicit pointer decay to perform that task.  The trick, if performed
intentionally, offers no efficiency gain over explicitly taking the address of
the array, but would fool a large number of subsequent code readers and
reviewers who are not familiar with this trick.  We do note that function
comparison performs exactly the same decay, and users are not surprised that
comparing functions is an identity test.
</p>

<p>
Given the likelihood that any usage of this comparison operator is a bug
waiting to be detected, this could be a real concern for software reliability.
Therefore, the strong recommendation is to remove this feature immediately from
C++23.  However, note for wording, that the comparison of an array with a
pointer value is <i>not</i> deprecated in C++20, is reasonably idiomatic for
practitioners of C++, and is intended to continue to be supported.  This mimics
the behavior of the spaceship operator.
</p>

<p>
Given the feature was so recently deprecated, the weak recommendation is to sit
on the feature for another 3 years giving users more time to find (presumably
benign) uses in their code and correct at a time of their choosing.  We would
expect to strongly recommend the removal again in another three years though,
rather than consider undeprecation for such a feature.
</p>


<blockquote class="recommend">
<b>Strong recommendation:</b>
Remove this feature from C++23
</blockquote>

<blockquote class="draft_wording">
<h4>7.6.9 Relational operators [expr.rel]</h4>
<ol>
<li>
The relational operators group left-to-right. [<i>Example:</i>
<tt>a&lt;b&lt;c</tt> means <tt>(a&lt;b)&lt;c</tt> and not
<tt>(a&lt;b)&amp;&amp;(b&lt;c)</tt>. <i>&mdash; end example</i>]
<blockquote><pre><i>
    relational-expression : compare-expression
    relational-expression &lt; compare-expression
    relational-expression &gt; compare-expression
    relational-expression &lt;= compare-expression
    relational-expression &gt;= compare-expression
</i></pre></blockquote>
The lvalue-to-rvalue (7.3.1)<del>, array-to-pointer (7.3.2),</del> and
function-to-pointer(7.3.3) standard conversions are performed on the operands.
<ins>
If at least one of the operands is of pointer type, array-to-pointer
conversions (7.3.2) are performed.
</ins>
<del>
The comparison is deprecated if both operands were of array type prior to these
conversions (D.4).
</del>
</li>
<li>
The converted operands shall have arithmetic, enumeration, or pointer type.
The operators <tt>&lt;</tt> (less than), <tt>&gt;</tt> (greater than),
<tt>&lt;=</tt> (less than or equal to), and <tt>&gt;=</tt> (greater than or equal
to) all yield <tt>false</tt> or <tt>true</tt>. The type of the result is
<tt>bool</tt>.
</li>
<li>
The usual arithmetic conversions (7.4) are performed on operands of arithmetic
or enumeration type. If both operands are pointers, pointer conversions
(7.3.11) and qualification conversions (7.3.5) are performed to bring them to
their composite pointer type (7.2.2). After conversions, the operands shall
have the same type.
</li>
<li>
The result of comparing unequal pointers to objects ...
</li>
</ol>

<h4>7.6.10 Equality operators [expr.eq]</h4>
<blockquote><pre><i>
equality-expression :
    relational-expression
    equality-expression == relational-expression
    equality-expression != relational-expression
</i></pre></blockquote>

<ol>
<li>
The <tt>==</tt> (equal to) and the <tt>!=</tt> (not equal to) operators group
left-to-right. The lvalue-to-rvalue (7.3.1)<del>, array-to-pointer
(7.3.2),</del> and function-to-pointer (7.3.3) standard conversions are
performed on the operands.
<del>
The comparison is deprecated if both operands
were of array type prior to these conversions (D.4).
</del>
</li>
<li>
If at least one of the operands is a pointer, <ins>array-to-pointer
conversions (7.3.2),</ins> pointer conversions (7.3.11), function
pointer conversions (7.3.13), and qualification conversions (7.3.5)
are performed on both operands to bring them to their composite
pointer type (7.2.2).
<del>
Comparing pointers is defined as follows:
</del>
</li>
<li>
The converted operands shall have arithmetic, enumeration, pointer,
or pointer-to-member type, or type <tt>std::nullptr_t</tt>. The
operators <tt>==</tt> and <tt>!=</tt> both yield <tt>true</tt> or
<tt>false</tt>, i.e., a result of type <tt>bool</tt>.  In each case
below, the operands shall have the same type after the specified
conversions have been applied.
</li>
<li>
<ins>
Comparing pointers is defined as follows:
</ins>
  <ol>
  <li>
  &mdash; If one pointer represents the address of a complete object,
  and another pointer represents the address one past the last element
  of a different complete object,<sup>79</sup> the result of the comparison is
  unspecified.
</li>
<li>
  &mdash; Otherwise, if the pointers are both null, both point to the
  same function, or both represent the same address (6.8.2), they
  compare equal.
</li>
<li>
  &mdash; Otherwise, the pointers compare unequal.
</li>
  </ol>
</li>
<li>
4 If at least one of the operands is a pointer to member, ...
</li>
</ol>

<h4><del>D.4 Array comparisons [depr.array.comp]</del></h4>
<ol>
<li>
<del>Equality and relational comparisons (7.6.10, 7.6.9) between two operands
of array type are deprecated. [<i>Note:</i> Three-way comparisons (7.6.8)
between such operands are ill-formed. <i>&mdash;end note</i>]
[<i>Example:</i></del>
<blockquote><pre>
<del>int arr1[5];</del>
<del>int arr2[5];</del>
<del>bool same = arr1 == arr2;       // deprecated, same as &amp;arr1[0] == &amp;arr2[0],</del>
                                <del>// does not compare array contents</del>
<del>auto cmp = arr1 &lt;=&gt; arr2;       // error</del>
</pre></blockquote>
<del><i>&mdash;end example</i>]</del>
</li>
</ol>
</blockquote>

<blockquote class="note">
We do not anticipate any impact on library wording by this removal.
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="review">
<b>EWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.5">D.5 Deprecated volatile types [depr.volatile.type]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
The <tt>volatile</tt> keyword is an original part of the C legacy for C++,
and describes constraints on programs intended to model hardware changing
values beyond the program's control.  As this entered the type system of
C++, certain interactions were discovered to be troublesome, and latent
bugs that could be detected at the time of program translation go unreported.
The paper

breaks down each context where the <tt>volatile</tt> keyword can be used,
and deprecated those uses that are unconditionally dangerous, or serve no
good purpose.  This paper is the first opportunity to go further, and
remove those use cases after 3 years of giving users deprecation warnings.
</p>

<p>
As outright removal is introducing potential breakage into programs that
have been compiling successfully since C++98, this paper strongly
recommends to hold this feature in Annex D as deprecated for another 3
years, and strongly consider taking further action for C++26.  However,
as there is the potential to diagnose real bugs for users to fix, the
weak recommendation is to remove these deprecated use cases immediatately
from C++23.  We note that it would also be possible to review each of the
4 noted usages separately, and remove only the most egregious cases of
latent bugs.
</p>


<blockquote class="recommend">
<b>Strong recommendation:</b>
Take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Remove this feature from C++23
</blockquote>

<!--- block comment to remove code --->

<blockquote class="note">
Draft removal from core wording
</blockquote>

<blockquote class="draft_wording">
<h4><del>D.5 Deprecated volatile types [depr.volatile.type]</del></h4>
<ol>
<li><del>
Postfix <tt>++</tt> and <tt>--</tt> expressions (7.6.1.5) and prefix
<tt>++</tt> and <tt>--</tt> expressions (7.6.2.2) of
<tt>volatile</tt>-qualified arithmetic and pointer types are deprecated.
</del></li>
<pre>
<del>[<i>Example:</i></del>
  <del>volatile int velociraptor;</del>
  <del>++velociraptor;                     <i>// deprecated</i></del>
<del><i>&mdash;end example</i>]</del>
</pre>

<li><del>
Certain assignments where the left operand is a <tt>volatile</tt>-qualified
non-class type are deprecated; see 7.6.19.
</del></li>
<pre>
<del>[<i>Example:</i></del>
  <del>int neck, tail;
  <del>volatile int brachiosaur;</del>
  <del>brachiosaur = neck;                 <i>// OK</i></del>
  <del>tail = brachiosaur;                 <i>// OK</i></del>
  <del>tail = brachiosaur = neck;          <i>// deprecated</i></del>
  <del>brachiosaur += neck;                <i>// deprecated</i></del>
  <del>brachiosaur = brachiosaur + neck;   <i>// OK</i></del>
<del><i>&mdash;end example</i>]</del>
</pre>

<li><del>
A function type (9.3.3.5) with a parameter with <tt>volatile</tt>-qualified
type or with a <tt>volatile</tt>-qualified return type is deprecated.
</del></li>
<pre>
<del>[<i>Example:</i></del>
  <del>volatile struct amber jurassic();                              <i>// deprecated</i></del>
  <del>void trex(volatile short left_arm, volatile short right_arm);  <i>// deprecated</i></del>
  <del>void fly(volatile struct pterosaur* pteranodon);               <i>// OK</i></del>
<del><i>&mdash;end example</i>]</del>
</pre>

<li><del>
A structured binding (9.6) of a <tt>volatile</tt>-qualified type is deprecated.
</del></li>
<pre>
<del>[<i>Example:</i></del>
  <del>struct linhenykus { short forelimb; };</del>
  <del>void park(linhenykus alvarezsauroid) {</del>
    <del>volatile auto [what_is_this] = alvarezsauroid;               <i>// deprecated</i></del>
    <del>// ...</del>
  <del>}</del>
<del><i>&mdash;end example</i>]</del>
</pre>

</ol>
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>
<!--- end of block comment to remove code -->


<blockquote class="review">
<b>EWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.6">D.6 Redeclaration of static constexpr data members [depr.static.constexpr]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++17
</blockquote>

<p>
Static constexpr data members were added to the language in C++11, as part of
the initial constexpr feature.  However, they still required a definition of
the member outside the class.  When inline variables were added in C++17
(<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0386r2">P0386R2</a>)
then static constexpr data members became implicitly inline, and the external
definition was redundant, and deprecated.
</p>
<p>
When we considered this feature for removal in C++20, it was thought the change
was too recent for users to have time to adjust, and recommended we reconsider
removal in C++23 (or later).
</p>
<p>
The feature seems relatively small and harmless; it is not clear that there is
a huge advantage to removing it immediately from C++23, although it would be
one less corner case to teach.  The strong recommendation is to retain this
feature, and reconsider removal in C++26, by which time the community will have
had most of a decade to clean up old C++11/14 code.
</p>
<p>
That said, there is also an argument to be made for cleanliness in the standard
and prompt removal of deprecated features.  If we were to remove this feature
early in the C++23 cycle, and compiler vendors expose this through their
experimental C++23 support, we would get early feedback if this were a step too
far, too soon.  The weak recommendation is to remove this feature from C++23.
</p>


<blockquote class="recommend">
<b>Strong recommendation:</b>
Take no action yet, consider again for C++26.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
remove this facility from C++23.
</blockquote>

<blockquote class="draft_wording">
<h4>6.1 Declarations and definitions [basic.def]</h4>
<ol start="2">
<li>
A declaration is a <i>definition</i> unless
  <ol>
<li>&mdash; it declares a function without specifying the function's body (11.4),</li>
<li>&mdash;
it contains the <tt>extern</tt> specifier (9.2.1) or a
<i>linkage-specification</i><sup>22</sup> (9.11) and neither an
<i>initializer</i> nor a <i>function-body</i>,
</li>
<li>&mdash; it declares a
non-inline static data member in a class definition (11.4, 11.4.8),
</li>
<li><del>&mdash;
it declares a static data member outside a class definition and the variable
was defined within the class with the <tt>constexpr</tt> specifier (this usage
is deprecated; see D.6),
</del></li>
<li>&mdash; it is introduced by an <i>elaborated-type-specifier</i> (11.3),</li>
<li>&mdash; it is an <i>opaque-enum-declaration</i> (9.7.1),</li>
<li>&mdash; it is a <i>template-parameter</i> (13.2),</li>
<li>&mdash; it is a <i>parameter-declaration</i> (9.3.3.5) in a function declarator that is not the <i>declarator</i> of a <i>function-definition</i>,</li>
<li>&mdash; it is a <tt>typedef</tt> declaration (9.2.3),</li>
<li>&mdash; it is an <i>alias-declaration</i> (9.2.3),</li>
<li>&mdash; it is a <i>using-declaration</i> (9.9),</li>
<li>&mdash; it is a <i>deduction-guide</i> (13.7.1.2),</li>
<li>&mdash; it is a <i>static_assert-declaration</i> ((9.1),</li>
<li>&mdash; it is an <i>attribute-declaration</i> ((9.1),</li>
<li>&mdash; it is an <i>empty-declaration</i> (9.1),</li>
<li>&mdash; it is a <i>using-directive</i> (9.8.3),</li>

<li>&mdash; it is a <i>using-enum-declaration</i> (9.7.2),</li>
<li>&mdash;
it is a <i>template-declaration</i> (13.1) whose <i>template-head</i> is not
followed by either a <i>concept-definition</i> or a declaration that defines a
function, a class, a variable, or a static data member.
</li>

<li>&mdash; it is an explicit instantiation declaration (13.9.2), or</li>
<li>&mdash; it is an explicit specialization (13.9.3) whose <i>declaration</i> is not a definition.</li>
  </ol>
</li>
</ol>

<h4>11.4.8.2 Static data members [class.static.data]</h4>
<ol start="4">
<li>
If a non-volatile non-inline <tt>const</tt> static data member is of integral or
enumeration type, its declaration in the class definition can specify a
<i>brace-or-equal-initializer</i> in which every <i>initializer-clause</i> that is an
<i>assignment-expression</i> is a constant expression (7.7). The member shall still
be defined in a namespace scope if it is odr-used (6.3) in the program and the
namespace scope definition shall not contain an <i>initializer</i>. An inline static
data member may be defined in the class definition and may specify a
<i>brace-or-equal-initializer</i>. <del>If the member is declared with the </tt>constexpr</tt>
specifier, it may be redeclared in namespace scope with no initializer (this
usage is deprecated; see D.6).</del> Declarations of other static data members shall
not specify a <i>brace-or-equal-initializer</i>.
</li>
</ol>

<h4><del>D.6 Redeclaration of static constexpr data members [depr.static.constexpr]</del></h4>
<ol>
<li><del>
For compatibility with prior C++ International Standards, a <tt>constexpr</tt> static data
member may be redundantly redeclared outside the class with no initializer. This usage is
deprecated. [ <i>Example:</i>
<blockquote><pre>
<del>struct A {</del>
  <del>static constexpr int n = 5; <i>// definition (declaration in C++ 2014)</i></del>
<del>};</del>

<del>constexpr int A::n;           <i>// redundant declaration (definition in C++ 2014)</i></del>
</pre></blockquote>
&mdash; <i>end example</i> ]
</del></li>
</ol>
</blockquote>

<blockquote class="note">
We do not anticipate any impact on library wording by this removal.
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="review">
<b>EWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.7">D.7 Non-local use of TU-local entities [depr.local]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This feature was deprecated as part of the effort to cleanly introduce modules
into the language, and was adopted by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1815r2">P1815R2</a>.
It potentially impacts on code written against C++98 and later standards.
</p>

<p>
This feature was deprecated only at the final meeting of the C++20 development cycle,
and at the time this paper is written, there is no experience with how much code has
been impacted by this deprecation.  As such, it is too early to make any recommendation
for a change with respect to this feature.
</p>


<blockquote class="recommend">
<b>Strong recommendation:</b>
take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="review">
<b>EWGI Review:</b>
To be determined...
</blockquote>



<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.8">D.8 Implicit declaration of copy functions [depr.impldec]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++11
</blockquote>

<p>
This feature was deprecated towards the end of the C++11 development cycle
by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3203">N3203</a>
and was heavily relied on prior to that.  That said, the deprecated features
are implicitly deleted if any move operations are declared, and users have
become familiar with this idiom over the last decade, and may now find the
older deprecated behavior jarring.
</p>
<p>
When we reviewed this facility for C++20, these was something of an impasse.
There was concern that removing this feature <i>ever</i> would break too much
code to ever consider it.  Conversely, there was no way to achieve a consensus
to undeprecate these features.  Finally, it was noted that no compiler had
ever issued a deprecation warning for these constructs, and all compiler
implementers present opined that they would never implement such a warning,
as it would flag far too much code to be a usable warning.
</p>
<p>
Since then, gcc has indeed implemented the warning, and incorporated into
its <tt>-Wall</tt> setting, the flag to turn on all the warnings that have
a vanishingly small false-positive rate.  The feedback from that exercise
was that coupling the destructor into the rule to delete copy operations
was indeed far too noisy, and unlikely to be realizable in production code.
Legitimate use case to implement a destructor unrelated to copy operation
occur too frequently in practice, such as a simple act of logging or
asserting invariants at the end of an object's lifetime.  However, the
coupling of the two copy operations produced a much lower (and tractable)
number of warnings, and found real bugs along with a number of false
positives.
</p>
<p>
The workaround for the issue is to simply declare the other copy member
in the class definition as <tt>= default</tt> so the fix is (mostly) simple,
easily hinted, and modern tools can even offer to apply the fix for you as
part of the warning.  There may be a concern that the fix relies on a C++11
feature, and so requires more work for code maintaining C++03 compatibility.
This is true, but for C++03 there is no functional difference between
generating the default and writing it by hand.  For C++11 the potential
difference is that a user-provided copy operation is no longer trivial, but
the distinction of decomposing PODs into trivial operations and standard
layout types matters only for C++11 onwards, as user-providing either
operation causes the type to not be a POD in C++03.
</p>

<p>
The strong recommendation of this paper is mixed: it is time to enforce
the rule coupling the copy operations in the same manner as the move
operations are coupled, and remove the legacy autogeneration if just one
is user-defined.  However, at the same time, we should uncouple the
destructor from this rule, undeprecating its impact on copy operations.
We might consider uncoupling the destructor from move operations for
consistency, but that would be a separate paper.
</p>
<p>
The weak recommendation is to continue another standard cycle with this
feature deprecated as-is, but consider what actions and research might
demonstrate we are ready to remove this coupling for C++26.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
take decisive action early in the C++23 development cycle, so early adopters
can shake out the remaining cost of updating old code.  Note that this would
be both an API and ABI breaking change, and it would be good to set that
precedent early if we wish to allow such breakage in C++23.
</blockquote>

<blockquote>
<h4>11.4.4.2 Copy/move constructors [class.copy.ctor]</h4>
<ol start="6">
<li>
<del>
If the class definition does not explicitly declare a copy constructor, a
non-explicit one is declared <i>implicitly</i>. If the class definition
declares a move constructor or move assignment operator, the implicitly
declared copy constructor is defined as deleted; otherwise, it is defined as
defaulted (9.5). The latter case is deprecated if the class has a
user-declared copy assignment operator or a user-declared destructor.
</del>
<p><ins>
If the definition of a class <tt>X</tt> does not explicitly declare a copy
constructor, a non-explicit one will be implicitly declared as defaulted if
and only if
  <ol>
  <li><ins>&mdash; <tt>X</tt> does not have a user-declared copy assignment operator,</ins></li>
  <li><ins>&mdash; <tt>X</tt> does not have a user-declared move constructor, and</ins></li>
  <li><ins>&mdash; <tt>X</tt> does not have a user-declared move assignment operator.</ins></li>
  </ol>
</ins></p>
  <blockquote class="note">
  User declared destructors are deliberately omitted from this list.  This
  wording undeprecates that concern - we could insert additional wording to
  retain the deprecated status when the class has a user-declared destructor.
  Note that we probably want the term "user-provided" as a user-declared
  <tt>= default</tt> destructor should not be a concern.
  </blockquote>
</li>
</ol>

<h4>11.4.5 Copy/move assignment operator [class.copy.assign]</h4>
<ol start="2">
<li><del>
If the class definition does not explicitly declare a copy assignment operator,
one is declared <i>implicitly</i>. If the class definition declares a move
constructor or move assignment operator, the implicitly declared copy assignment
operator is defined as deleted; otherwise, it is defined as defaulted (9.5).
The latter case is deprecated if the class has a user-declared copy
constructor or a user-declared destructor.</del>
<p><ins>
If the definition of a class <tt>X</tt> does not explicitly declare a copy
assignment operator, one will be implicitly declared as defaulted if and only if
  <ol>
  <li><ins>&mdash; <tt>X</tt> does not have a user-declared copy constructor,</ins></li>
  <li><ins>&mdash; <tt>X</tt> does not have a user-declared move constructor, and</ins></li>
  <li><ins>&mdash; <tt>X</tt> does not have a user-declared move assignment operator.</ins></li>
  </ol>
</ins></p>
  <blockquote class="note">
  User declared destructors are deliberately omitted from this list.  This
  wording undeprecates that concern - we could insert additional wording to
  retain the deprecated status when the class has a user-declared destructor.
  Note that we probably want the term "user-provided" as a user-declared
  <tt>= default</tt> destructor should not be a concern.
  </blockquote>
</li>
<li>
The implicitly-declared copy assignment operator for a class <tt>X</tt> will
have the form...
</li>
</ol>


<h4><del>D.8 Implicit declaration of copy functions [depr.impldec]</del></h4>
<ol>
<li><del>
The implicit definition of a copy constructor as defaulted is deprecated if the
class has a user-declared copy assignment operator or a user-declared
destructor. The implicit definition of a copy assignment operator as defaulted
is deprecated if the class has a user-declared copy constructor or a
user-declared destructor (15.4, 15.8). In a future revision of this
International Standard, these implicit definitions could become deleted (11.4).
</del></li>
</ol>
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
take no action now, and plan to remove this feature in the next revision of
the standard that will permit both ABI and API breakage.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="review">
<b>EWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.9">D.9 C headers [depr.c.headers]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++98
</blockquote>

<p>
The basic C library headers are an essential compatibility feature, and not
going anywhere anytime soon.  However, there are certain C++ specific
counterparts that do not bring value, particularly where the corresponding C
header's job is to supply macros that masquerade as keywords already present in
the C++ language.
</p>

<p>
One possibility to be more aggressive here, following the decision to not adopt
<i>all</i> C11 headers as part of the C++ mapping to C, would be to remove
those same C headers from the subset that must be shipped with a C++ compiler.
The corresponding change for the C++ <tt>&lt;cstd*&gt;</tt> was accepted for
C++20.  This would not prevent those headers being supplied, as part of a full
C implementation, but would indicate that they have no value to a C++ system.
</p>

<p>
Finally, it seems clear that the C headers will be retained essentially
forever, as a vital compatibility layer with C and POSIX.  It seems appropriate
to undeprecate the headers, and find a home for them as a compatibility layer
in the main standard.  It is also possible that we will want to explore a
different approach in the future once modules are part of C++, and the library
is updated to properly take advantage of the new language feature.
</p>

<p>
The strong recommendation of this paper is to undeprecate the C library as an
essential compatibility layer with the rest of the world, optionally removing
the vacuous headers.
</p>
<p>
The weak recommendation is to remove these entirely from C++23: these headers
are already owned and specified by at least two other ISO committees, and while
C compatibility is an essential feature for any C++ tool chain sitting on POSIX,
it may be overspecification demanding what should be platform implementation
details for other environments - as noted when C++17 chose to not require the
C <tt>&lt;atomic.h&gt;</tt>.
</p>

<blockquote class="recommend">
<b>Strong recommendation(A):</b>
Undeprecate the remaining <b>[depr.c.headers]</b> and move directly into
16.5.5.2 <b>[res.on.headers]</b>.  Then remove the vacuous headers.
</blockquote>

<blockquote class="note">
As above, but with the following tweaks:
</blockquote>

<blockquote class="draft_wording">
<h4><ins>16.5.5.2.1 C standard library headers [c.headers]</ins></h4>
<ol>
<li><ins>
For compatibility with the C standard library, the C++ standard library
provides the C headers shown in Table 145.
</ins></li>
<p><ins>
Table 145 &mdash; C headers
</ins></p>
<table>
  <tr>
    <td><tt><ins>&lt;assert.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;inttypes.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;signal.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;stdio.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;wchar.h&gt;</ins></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;complex.h&gt;</del></tt></td>
    <td><tt><del>&lt;iso646.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdalign.h&gt;</del></tt></td>
    <td><tt><ins>&lt;stdlib.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;wctype.h&gt;</ins></tt></td>
  </tr>
  <tr>
    <td><tt><ins>&lt;ctype.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;limits.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;stdarg.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;string.h&gt;</ins></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><ins>&lt;errno.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;locale.h&gt;</ins></tt></td>
    <td><tt><del>&lt;stdbool.h&gt;</del></tt></td>
    <td><tt><del>&lt;tgmath.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><ins>&lt;fenv.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;math.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;stddef.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;time.h&gt;</ins></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><ins>&lt;float.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;setjmp.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;stdint.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;uchar.h&gt;</ins></tt></td>
    <td><tt></tt></td>
  </tr>
</table>

<li><ins>
Every C header, each of which has a name of the form <tt>&lt;name.h&gt;</tt>,
behaves as if each name placed in the standard library namespace by the
corresponding <tt>&lt;cname&gt;</tt> header is placed within the global
namespace scope, except for the functions described in 26.8.6, the declarations
of <tt>std::nullptr_t</tt> (17.2.3) and <tt>std::byte</tt> (17.2.5), and the functions
and function templates described in 17.2.5. It is unspecified whether these
names are first declared or defined within namespace scope (6.4.6) of the
namespace <tt>std</tt> and are then injected into the global namespace scope by
explicit using-declarations (9.9).
</ins></li>
<li><ins>
[<i>Example:</i> The header <tt>&lt;cstdlib&gt;</tt> assuredly provides its
declarations and definitions within the namespace <tt>std</tt>. It may also
provide these names within the global namespace. The header
<tt>&lt;stdlib.h&gt;</tt> assuredly provides the same declarations and
definitions within the global namespace, much as in the C Standard. It may also
provide these names within the namespace <tt>std</tt>. <i>&mdash;end
example</i>]
</ins></li>
</ol>

<h4><del>D.9 C headers [depr.c.headers]</del></h4>
<ol>
<li><del>
For compatibility with the C standard library, the C++ standard library
provides the <i>C headers</i> shown in Table 145.
</del></li>
<p><del>
Table 145 &mdash; C headers
</del></p>
<table>
  <tr>
    <td><tt><del>&lt;assert.h&gt;</del></tt></td>
    <td><tt><del>&lt;inttypes.h&gt;</del></tt></td>
    <td><tt><del>&lt;signal.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdio.h&gt;</del></tt></td>
    <td><tt><del>&lt;wchar.h&gt;</del></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;complex.h&gt;</del></tt></td>
    <td><tt><del>&lt;iso646.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdalign.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdlib.h&gt;</del></tt></td>
    <td><tt><del>&lt;wctype.h&gt;</del></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;ctype.h&gt;</del></tt></td>
    <td><tt><del>&lt;limits.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdarg.h&gt;</del></tt></td>
    <td><tt><del>&lt;string.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;errno.h&gt;</del></tt></td>
    <td><tt><del>&lt;locale.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdbool.h&gt;</del></tt></td>
    <td><tt><del>&lt;tgmath.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;fenv.h&gt;</del></tt></td>
    <td><tt><del>&lt;math.h&gt;</del></tt></td>
    <td><tt><del>&lt;stddef.h&gt;</del></tt></td>
    <td><tt><del>&lt;time.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;float.h&gt;</del></tt></td>
    <td><tt><del>&lt;setjmp.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdint.h&gt;</del></tt></td>
    <td><tt><del>&lt;uchar.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
</table>
</ol>

<h4><del>D.9.1 Header <tt>&lt;complex.h&gt;</tt> synopsis [depr.complex.h.syn]</del></h4>
<pre><del>#include <tt>&lt;complex&gt;</tt></del></pre>
<ol>
<li><del>
The header <tt>&lt;complex.h&gt;</tt> behaves as if it simply includes the
header <tt>&lt;complex&gt;</tt> (26.4.1).
</del></li>
<li><del>
[<i>Note:</i> Names introduced by <tt>&lt;complex&gt;</tt> in namespace
<tt>std</tt> are not placed into the global namespace scope by
<tt>&lt;complex.h&gt;</tt>. <i>&mdash;end note</i>]
</del></li>
</ol>


<h4><del>D.9.2 Header <tt>&lt;iso646.h&gt;</tt> synopsis [depr.iso646.h.syn]</del></h4>
<ol>
<li><del>
The C++ header <tt>&lt;iso646.h&gt;</tt> is empty. [<i>Note:</i> <tt>and</tt>,
<tt>and_eq</tt>, <tt>bitand</tt>, <tt>bitor</tt>, <tt>compl</tt>,
<tt>not_eq</tt>, <tt>not</tt>, <tt>or</tt>, <tt>or_eq</tt>, <tt>xor</tt>, and
<tt>xor_eq</tt> are keywords in this International Standard (5.11).
<i>&mdash;end note</i>]
</del></li>
</ol>


<h4><del>D.9.3 Header <tt>&lt;stdalign.h&gt;</tt> synopsis [depr.stdalign.h.syn]</del></h4>
<pre><del>#define __alignas_is_defined 1</del></pre>
<ol>
<li><del>
The contents of the C++ header <tt>&lt;stdalign.h&gt;</tt> are the same as the
C standard library header <tt>&lt;stdalign.h&gt;</tt>, with the following
changes: The header <tt>&lt;stdalign.h&gt;</tt> does not define a macro named
alignas.</del>
<p><del>See also: ISO C 7.15</del></p>
</li>
</ol>


<h4><del>D.9.4 Header <tt>&lt;stdbool.h&gt;</tt> synopsis [depr.stdbool.h.syn]</del></h4>
<pre><del>#define __bool_true_false_are_defined 1</del></pre>
<ol>
<li><del>
The contents of the C++ header <tt>&lt;stdbool.h&gt;</tt> are the same as the C
standard library header <tt>&lt;stdbool.h&gt;</tt>, with the following changes:
The header <tt>&lt;stdbool.h&gt;</tt> does not define macros named
<tt>bool</tt>, <tt>true</tt>, or <tt>false</tt>.</del>
<p><del>See also: ISO C 7.18</del></p>
</li>
</ol>


<h4><del>D.9.5 Header <tt>&lt;tgmath.h&gt;</tt> synopsis [depr.tgmath.h.syn]</del></h4>
<pre>
<del>#include <tt>&lt;cmath&gt;</tt></del>
<del>#include <tt>&lt;complex&gt;</tt></del>
</pre>
<ol>
<li><del>
The header <tt>&lt;tgmath.h&gt;</tt> behaves as if it simply includes the
headers <tt>&lt;cmath&gt;</tt> (26.8.1) and <tt>&lt;complex&gt;</tt> (26.4.1).
</del></li>
<li><del>
[<i>Note:</i> The overloads provided in C by type-generic macros are already
provided in <tt>&lt;complex&gt;</tt> and <tt>&lt;cmath&gt;</tt> by “sufficient”
additional overloads. <i>&mdash;end note</i>]
</del></li>
<li><del>
[<i>Note:</i> Names introduced by <tt>&lt;cmath&gt;</tt> or
<tt>&lt;complex&gt;</tt> in namespace std are not placed into the global
namespace scope by <tt>&lt;tgmath.h&gt;</tt>. <i>&mdash;end note</i>]
</del></li>
</ol>


<h4><del>D.9.6 Other C headers [depr.c.headers.other]</del></h4>
<ol>
<li><del>
Every C header other than <tt>&lt;complex.h&gt;</tt> (D.9.1),
<tt>&lt;iso646.h&gt;</tt> (D.9.2), <tt>&lt;stdalign.h&gt;</tt> (D.9.3),
<tt>&lt;stdbool.h&gt;</tt> (D.9.4), and <tt>&lt;tgmath.h&gt;</tt> (D.9.5), each
of which has a name of the form <tt>&lt;name.h&gt;</tt>, behaves as if each
name placed in the standard library namespace by the corresponding
<tt>&lt;cname&gt;</tt> header is placed within the global namespace scope,
except for the functions described in 26.8.6, the declaration of
<tt>std::byte</tt> (17.2.1), and the functions and function templates described
in 17.2.5. It is unspecified whether these names are first declared or defined
within namespace scope (6.4.6) of the namespace <tt>std</tt> and are then
injected into the global namespace scope by explicit using-declarations (9.9).
</del></li>
<li><del>
[<i>Example:</i> The header <tt>&lt;cstdlib&gt;</tt> assuredly provides its
declarations and definitions within the namespace <tt>std</tt>. It may also
provide these names within the global namespace. The header
<tt>&lt;stdlib.h&gt;</tt> assuredly provides the same declarations and
definitions within the global namespace, much as in the C Standard. It may also
provide these names within the namespace <tt>std</tt>. <i>&mdash;end
example</i>]
</del></li>
</ol>

<h4>C.6.1 Modifications to headers [diff.mods.to.headers]</h4>
<ol>
<li>
For compatibility with the C standard library, the C++ standard library provides the
C headers enumerated in <del>D.9, but their use is deprecated in C++</del>
<ins><b>[c.headers]</b></ins>.
</li>
<li>
There are no C++ headers for the C headers <ins><tt>&lt;complex.h&gt;</tt>,</ins>
<tt>&lt;stdatomic.h&gt;</tt>, <ins><tt>&lt;iso646.h&gt;</tt>, <tt>&lt;stdalign.h&gt;</tt>,
<tt>&lt;stdbool.h&gt;</tt>,</ins> <tt>&lt;stdnoreturn.h&gt;</tt>,
<ins><tt>&lt;tgmath.h&gt;</tt>,</ins> and <tt>&lt;threads.h&gt;</tt>, nor are the C headers
themselves part of C++.
</li>
<li><del>
The headers <tt>&lt;ccomplex&gt;</tt> (29.5.11) and <tt>&lt;ctgmath&gt;</tt>
(29.9.6), as well as their corresponding C headers <tt>&lt;complex.h&gt;</tt>
and <tt>&lt;tgmath.h&gt;</tt>, do not contain any of the content from the C
standard library and instead merely include other headers from the C++ standard library.
</del></li>
<li><del>
The headers <tt>&lt;ciso646&gt;</tt>, <tt>&lt;cstdalign&gt;</tt> (21.10.4), and
<tt>&lt;cstdbool&gt;</tt> (21.10.3) are meaningless in C++. Use of the C++ headers
<tt>&lt;ccomplex&gt;</tt>,  <tt>&lt;cstdalign&gt;</tt>, <tt>&lt;cstdbool&gt;</tt>, and
<tt>&lt;ctgmath&gt;</tt> is deprecated (D.4).
</del></li>
</ol>
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="recommend">
<b>strong recommendation (B):</b>
Undeprecate the remaining <b>[depr.c.headers]</b> and move directly into
16.5.5.2 <b>[res.on.headers]</b>.
</blockquote>

<blockquote class="draft_wording">
<h4>16.5.5.2 Headers [res.on.headers]</h4>
<ol>
<li>
A C++ header may include other C++ headers. A C++ header shall provide the
declarations and definitions that appear in its synopsis. A C++ header shown in
its synopsis as including other C++ headers shall provide the declarations and
definitions that appear in the synopses of those other headers.
</li>
<li>
Certain types and macros are defined in more than one header. Every such entity
shall be defined such that any header that defines it may be included after any
other header that also defines it (6.3).
</li>
<li><del>
The C standard library headers (D.9) shall include only their corresponding C++
standard library header, as described in 16.5.1.2.
</li>
</del></ol>

<blockquote class="note">
Actually, probably want to merge this into <b>16.5.1.2 Headers [headers]</b>.
Also, fix up cross-references to list stable labels.
</blockquote>
<h4><ins>16.5.5.2.1 C headers [c.headers]</ins></h4>
<ol>
<li><ins>
For compatibility with the C standard library, the C++ standard library
provides the <i>C headers</i> shown in Table 145.
</ins></li>
<p><ins>
Table 145 &mdash; C headers
</ins></p>
<table>
  <tr>
    <td><tt><ins>&lt;assert.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;inttypes.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;signal.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;stdio.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;wchar.h&gt;</ins></tt></td>
  </tr>
  <tr>
    <td><tt><ins>&lt;complex.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;iso646.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;stdalign.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;stdlib.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;wctype.h&gt;</ins></tt></td>
  </tr>
  <tr>
    <td><tt><ins>&lt;ctype.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;limits.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;stdarg.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;string.h&gt;</ins></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><ins>&lt;errno.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;locale.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;stdbool.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;tgmath.h&gt;</ins></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><ins>&lt;fenv.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;math.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;stddef.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;time.h&gt;</ins></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><ins>&lt;float.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;setjmp.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;stdint.h&gt;</ins></tt></td>
    <td><tt><ins>&lt;uchar.h&gt;</ins></tt></td>
    <td><tt></tt></td>
  </tr>
</table>
</ol>

<h4><ins>16.5.5.2.1.1 Header <tt>&lt;complex.h&gt;</tt> synopsis [complex.h.syn]</ins></h4>
<pre><ins>#include <tt>&lt;complex&gt;</tt></ins></pre>
<ol>
<li><ins>
The header <tt>&lt;complex.h&gt;</tt> behaves as if it simply includes the
header <tt>&lt;complex&gt;</tt> (26.4.1).
</ins></li>
<li><ins>
[<i>Note:</i> Names introduced by <tt>&lt;complex&gt;</tt> in namespace
<tt>std</tt> are not placed into the global namespace scope by
<tt>&lt;complex.h&gt;</tt>. <i>&mdash;end note</i>]
</ins></li>
</ol>

<h4><ins>16.5.5.2.1.2 Header <tt>&lt;iso646.h&gt;</tt> synopsis [iso646.h.syn]</ins></h4>
<ol>
<li><ins>
The C++ header <tt>&lt;iso646.h&gt;</tt> is empty. [<i>Note:</i> <tt>and</tt>,
<tt>and_eq</tt>, <tt>bitand</tt>, <tt>bitor</tt>, <tt>compl</tt>,
<tt>not_eq</tt>, <tt>not</tt>, <tt>or</tt>, <tt>or_eq</tt>, <tt>xor</tt>, and
<tt>xor_eq</tt> are keywords in this International Standard (5.11).
<i>&mdash;end note</i>]
</ins></li>
</ol>

<h4><ins>16.5.5.2.1.3 Header <tt>&lt;stdalign.h&gt;</tt> synopsis [stdalign.h.syn]</ins></h4>
<pre><ins>#define __alignas_is_defined 1</ins></pre>
<ol>
<li><ins>
The contents of the C++ header <tt>&lt;stdalign.h&gt;</tt> are the same as the
C standard library header <tt>&lt;stdalign.h&gt;</tt>, with the following
changes: The header <tt>&lt;stdalign.h&gt;</tt> does not define a macro named
alignas.</ins>
<p><ins>See also: ISO C 7.15</ins></p>
</li>
</ol>

<h4><ins>16.5.5.2.1.4 Header <tt>&lt;stdbool.h&gt;</tt> synopsis [stdbool.h.syn]</ins></h4>
<pre><ins>#define __bool_true_false_are_defined 1</ins></pre>
<ol>
<li><ins>
The contents of the C++ header <tt>&lt;stdbool.h&gt;</tt> are the same as the C
standard library header <tt>&lt;stdbool.h&gt;</tt>, with the following changes:
The header <tt>&lt;stdbool.h&gt;</tt> does not define macros named
<tt>bool</tt>, <tt>true</tt>, or <tt>false</tt>.</ins>
<p><ins>See also: ISO C 7.18</ins></p>
</li>
</ol>

<h4><ins>16.5.5.2.1.5 Header <tt>&lt;tgmath.h&gt;</tt> synopsis [tgmath.h.syn]</ins></h4>
<pre>
<ins>#include <tt>&lt;cmath&gt;</tt></ins>
<ins>#include <tt>&lt;complex&gt;</tt></ins>
</pre>
<ol>
<li><ins>
The header <tt>&lt;tgmath.h&gt;</tt> behaves as if it simply includes the
headers <tt>&lt;cmath&gt;</tt> (26.8.1) and <tt>&lt;complex&gt;</tt> (26.4.1).
</ins></li>
<li><ins>
[<i>Note:</i> The overloads provided in C by type-generic macros are already
provided in <tt>&lt;complex&gt;</tt> and <tt>&lt;cmath&gt;</tt> by “sufficient”
additional overloads. <i>&mdash;end note</i>]
</ins></li>
<li><ins>
[<i>Note:</i> Names introduced by <tt>&lt;cmath&gt;</tt> or
<tt>&lt;complex&gt;</tt> in namespace std are not placed into the global
namespace scope by <tt>&lt;tgmath.h&gt;</tt>. <i>&mdash;end note</i>]
</ins></li>
</ol>

<h4><ins>16.5.5.2.1.6 Other C headers [c.headers.other]</ins></h4>
<ol>
<li><ins>
Every C header other than <tt>&lt;complex.h&gt;</tt> (D.9.1),
<tt>&lt;iso646.h&gt;</tt> (D.9.2), <tt>&lt;stdalign.h&gt;</tt> (D.9.3),
<tt>&lt;stdbool.h&gt;</tt> (D.9.4), and <tt>&lt;tgmath.h&gt;</tt> (D.9.5), each
of which has a name of the form <tt>&lt;name.h&gt;</tt>, behaves as if each
name placed in the standard library namespace by the corresponding
<tt>&lt;cname&gt;</tt> header is placed within the global namespace scope,
except for the functions described in 26.8.6, the declaration of
<tt>std::byte</tt> (17.2.1), and the functions and function templates described
in 17.2.5. It is unspecified whether these names are first declared or defined
within namespace scope (6.4.6) of the namespace <tt>std</tt> and are then
injected into the global namespace scope by explicit using-declarations (9.9).
</ins></li>
<li><ins>
[<i>Example:</i> The header <tt>&lt;cstdlib&gt;</tt> assuredly provides its
declarations and definitions within the namespace <tt>std</tt>. It may also
provide these names within the global namespace. The header
<tt>&lt;stdlib.h&gt;</tt> assuredly provides the same declarations and
definitions within the global namespace, much as in the C Standard. It may also
provide these names within the namespace <tt>std</tt>. <i>&mdash;end
example</i>]
</ins></li>
</ol>


<h4><del>D.9 C headers [depr.c.headers]</del></h4>
<ol>
<li><del>
For compatibility with the C standard library, the C++ standard library
provides the <i>C headers</i> shown in Table 145.
</del></li>
<p><del>
Table 145 &mdash; C headers
</del></p>
<table>
  <tr>
    <td><tt><del>&lt;assert.h&gt;</del></tt></td>
    <td><tt><del>&lt;inttypes.h&gt;</del></tt></td>
    <td><tt><del>&lt;signal.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdio.h&gt;</del></tt></td>
    <td><tt><del>&lt;wchar.h&gt;</del></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;complex.h&gt;</del></tt></td>
    <td><tt><del>&lt;iso646.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdalign.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdlib.h&gt;</del></tt></td>
    <td><tt><del>&lt;wctype.h&gt;</del></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;ctype.h&gt;</del></tt></td>
    <td><tt><del>&lt;limits.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdarg.h&gt;</del></tt></td>
    <td><tt><del>&lt;string.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;errno.h&gt;</del></tt></td>
    <td><tt><del>&lt;locale.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdbool.h&gt;</del></tt></td>
    <td><tt><del>&lt;tgmath.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;fenv.h&gt;</del></tt></td>
    <td><tt><del>&lt;math.h&gt;</del></tt></td>
    <td><tt><del>&lt;stddef.h&gt;</del></tt></td>
    <td><tt><del>&lt;time.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;float.h&gt;</del></tt></td>
    <td><tt><del>&lt;setjmp.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdint.h&gt;</del></tt></td>
    <td><tt><del>&lt;uchar.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
</table>
</ol>

<h4><del>D.9.1 Header <tt>&lt;complex.h&gt;</tt> synopsis [depr.complex.h.syn]</del></h4>
<pre><del>#include <tt>&lt;complex&gt;</tt></del></pre>
<ol>
<li><del>
The header <tt>&lt;complex.h&gt;</tt> behaves as if it simply includes the
header <tt>&lt;complex&gt;</tt> (26.4.1).
</del></li>
<li><del>
[<i>Note:</i> Names introduced by <tt>&lt;complex&gt;</tt> in namespace
<tt>std</tt> are not placed into the global namespace scope by
<tt>&lt;complex.h&gt;</tt>. <i>&mdash;end note</i>]
</del></li>
</ol>


<h4><del>D.9.2 Header <tt>&lt;iso646.h&gt;</tt> synopsis [depr.iso646.h.syn]</del></h4>
<ol>
<li><del>
The C++ header <tt>&lt;iso646.h&gt;</tt> is empty. [<i>Note:</i> <tt>and</tt>,
<tt>and_eq</tt>, <tt>bitand</tt>, <tt>bitor</tt>, <tt>compl</tt>,
<tt>not_eq</tt>, <tt>not</tt>, <tt>or</tt>, <tt>or_eq</tt>, <tt>xor</tt>, and
<tt>xor_eq</tt> are keywords in this International Standard (5.11).
<i>&mdash;end note</i>]
</del></li>
</ol>


<h4><del>D.9.3 Header <tt>&lt;stdalign.h&gt;</tt> synopsis [depr.stdalign.h.syn]</del></h4>
<pre><del>#define __alignas_is_defined 1</del></pre>
<ol>
<li><del>
The contents of the C++ header <tt>&lt;stdalign.h&gt;</tt> are the same as the
C standard library header <tt>&lt;stdalign.h&gt;</tt>, with the following
changes: The header <tt>&lt;stdalign.h&gt;</tt> does not define a macro named
alignas.</del>
<p><del>See also: ISO C 7.15</del></p>
</li>
</ol>


<h4><del>D.9.4 Header <tt>&lt;stdbool.h&gt;</tt> synopsis [depr.stdbool.h.syn]</del></h4>
<pre><del>#define __bool_true_false_are_defined 1</del></pre>
<ol>
<li><del>
The contents of the C++ header <tt>&lt;stdbool.h&gt;</tt> are the same as the C
standard library header <tt>&lt;stdbool.h&gt;</tt>, with the following changes:
The header <tt>&lt;stdbool.h&gt;</tt> does not define macros named
<tt>bool</tt>, <tt>true</tt>, or <tt>false</tt>.</del>
<p><del>See also: ISO C 7.18</del></p>
</li>
</ol>


<h4><del>D.9.5 Header <tt>&lt;tgmath.h&gt;</tt> synopsis [depr.tgmath.h.syn]</del></h4>
<pre>
<del>#include <tt>&lt;cmath&gt;</tt></del>
<del>#include <tt>&lt;complex&gt;</tt></del>
</pre>
<ol>
<li><del>
The header <tt>&lt;tgmath.h&gt;</tt> behaves as if it simply includes the
headers <tt>&lt;cmath&gt;</tt> (26.8.1) and <tt>&lt;complex&gt;</tt> (26.4.1).
</del></li>
<li><del>
[<i>Note:</i> The overloads provided in C by type-generic macros are already
provided in <tt>&lt;complex&gt;</tt> and <tt>&lt;cmath&gt;</tt> by “sufficient”
additional overloads. <i>&mdash;end note</i>]
</del></li>
<li><del>
[<i>Note:</i> Names introduced by <tt>&lt;cmath&gt;</tt> or
<tt>&lt;complex&gt;</tt> in namespace std are not placed into the global
namespace scope by <tt>&lt;tgmath.h&gt;</tt>. <i>&mdash;end note</i>]
</del></li>
</ol>


<h4><del>D.9.6 Other C headers [depr.c.headers.other]</del></h4>
<ol>
<li><del>
Every C header other than <tt>&lt;complex.h&gt;</tt> (D.9.1),
<tt>&lt;iso646.h&gt;</tt> (D.9.2), <tt>&lt;stdalign.h&gt;</tt> (D.9.3),
<tt>&lt;stdbool.h&gt;</tt> (D.9.4), and <tt>&lt;tgmath.h&gt;</tt> (D.9.5), each
of which has a name of the form <tt>&lt;name.h&gt;</tt>, behaves as if each
name placed in the standard library namespace by the corresponding
<tt>&lt;cname&gt;</tt> header is placed within the global namespace scope,
except for the functions described in 26.8.6, the declaration of
<tt>std::byte</tt> (17.2.1), and the functions and function templates described
in 17.2.5. It is unspecified whether these names are first declared or defined
within namespace scope (6.4.6) of the namespace <tt>std</tt> and are then
injected into the global namespace scope by explicit using-declarations (9.9).
</del></li>
<li><del>
[<i>Example:</i> The header <tt>&lt;cstdlib&gt;</tt> assuredly provides its
declarations and definitions within the namespace <tt>std</tt>. It may also
provide these names within the global namespace. The header
<tt>&lt;stdlib.h&gt;</tt> assuredly provides the same declarations and
definitions within the global namespace, much as in the C Standard. It may also
provide these names within the namespace <tt>std</tt>. <i>&mdash;end
example</i>]
</del></li>
</ol>

</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Remove entirely from C++23.
</blockquote>

<blockquote class="draft_wording">
<h4><del>D.9 C headers [depr.c.headers]</del></h4>
<ol>
<li><del>
For compatibility with the C standard library, the C++ standard library
provides the <i>C headers</i> shown in Table 145.
</del></li>
<p><del>
Table 145 &mdash; C headers
</del></p>
<table>
  <tr>
    <td><tt><del>&lt;assert.h&gt;</del></tt></td>
    <td><tt><del>&lt;inttypes.h&gt;</del></tt></td>
    <td><tt><del>&lt;signal.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdio.h&gt;</del></tt></td>
    <td><tt><del>&lt;wchar.h&gt;</del></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;complex.h&gt;</del></tt></td>
    <td><tt><del>&lt;iso646.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdalign.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdlib.h&gt;</del></tt></td>
    <td><tt><del>&lt;wctype.h&gt;</del></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;ctype.h&gt;</del></tt></td>
    <td><tt><del>&lt;limits.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdarg.h&gt;</del></tt></td>
    <td><tt><del>&lt;string.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;errno.h&gt;</del></tt></td>
    <td><tt><del>&lt;locale.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdbool.h&gt;</del></tt></td>
    <td><tt><del>&lt;tgmath.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;fenv.h&gt;</del></tt></td>
    <td><tt><del>&lt;math.h&gt;</del></tt></td>
    <td><tt><del>&lt;stddef.h&gt;</del></tt></td>
    <td><tt><del>&lt;time.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;float.h&gt;</del></tt></td>
    <td><tt><del>&lt;setjmp.h&gt;</del></tt></td>
    <td><tt><del>&lt;stdint.h&gt;</del></tt></td>
    <td><tt><del>&lt;uchar.h&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
</table>
</ol>

<h4><del>D.9.1 Header <tt>&lt;complex.h&gt;</tt> synopsis [depr.complex.h.syn]</del></h4>
<pre><del>#include <tt>&lt;complex&gt;</tt></del></pre>
<ol>
<li><del>
The header <tt>&lt;complex.h&gt;</tt> behaves as if it simply includes the
header <tt>&lt;complex&gt;</tt> (26.4.1).
</del></li>
<li><del>
[<i>Note:</i> Names introduced by <tt>&lt;complex&gt;</tt> in namespace
<tt>std</tt> are not placed into the global namespace scope by
<tt>&lt;complex.h&gt;</tt>. <i>&mdash;end note</i>]
</del></li>
</ol>


<h4><del>D.9.2 Header <tt>&lt;iso646.h&gt;</tt> synopsis [depr.iso646.h.syn]</del></h4>
<ol>
<li><del>
The C++ header <tt>&lt;iso646.h&gt;</tt> is empty. [<i>Note:</i> <tt>and</tt>,
<tt>and_eq</tt>, <tt>bitand</tt>, <tt>bitor</tt>, <tt>compl</tt>,
<tt>not_eq</tt>, <tt>not</tt>, <tt>or</tt>, <tt>or_eq</tt>, <tt>xor</tt>, and
<tt>xor_eq</tt> are keywords in this International Standard (5.11).
<i>&mdash;end note</i>]
</del></li>
</ol>


<h4><del>D.9.3 Header <tt>&lt;stdalign.h&gt;</tt> synopsis [depr.stdalign.h.syn]</del></h4>
<pre><del>#define __alignas_is_defined 1</del></pre>
<ol>
<li><del>
The contents of the C++ header <tt>&lt;stdalign.h&gt;</tt> are the same as the
C standard library header <tt>&lt;stdalign.h&gt;</tt>, with the following
changes: The header <tt>&lt;stdalign.h&gt;</tt> does not define a macro named
alignas.</del>
<p><del>See also: ISO C 7.15</del></p>
</li>
</ol>


<h4><del>D.9.4 Header <tt>&lt;stdbool.h&gt;</tt> synopsis [depr.stdbool.h.syn]</del></h4>
<pre><del>#define __bool_true_false_are_defined 1</del></pre>
<ol>
<li><del>
The contents of the C++ header <tt>&lt;stdbool.h&gt;</tt> are the same as the C
standard library header <tt>&lt;stdbool.h&gt;</tt>, with the following changes:
The header <tt>&lt;stdbool.h&gt;</tt> does not define macros named
<tt>bool</tt>, <tt>true</tt>, or <tt>false</tt>.</del>
<p><del>See also: ISO C 7.18</del></p>
</li>
</ol>


<h4><del>D.9.5 Header <tt>&lt;tgmath.h&gt;</tt> synopsis [depr.tgmath.h.syn]</del></h4>
<pre>
<del>#include <tt>&lt;cmath&gt;</tt></del>
<del>#include <tt>&lt;complex&gt;</tt></del>
</pre>
<ol>
<li><del>
The header <tt>&lt;tgmath.h&gt;</tt> behaves as if it simply includes the
headers <tt>&lt;cmath&gt;</tt> (26.8.1) and <tt>&lt;complex&gt;</tt> (26.4.1).
</del></li>
<li><del>
[<i>Note:</i> The overloads provided in C by type-generic macros are already
provided in <tt>&lt;complex&gt;</tt> and <tt>&lt;cmath&gt;</tt> by “sufficient”
additional overloads. <i>&mdash;end note</i>]
</del></li>
<li><del>
[<i>Note:</i> Names introduced by <tt>&lt;cmath&gt;</tt> or
<tt>&lt;complex&gt;</tt> in namespace std are not placed into the global
namespace scope by <tt>&lt;tgmath.h&gt;</tt>. <i>&mdash;end note</i>]
</del></li>
</ol>


<h4><del>D.9.6 Other C headers [depr.c.headers.other]</del></h4>
<ol>
<li><del>
Every C header other than <tt>&lt;complex.h&gt;</tt> (D.9.1),
<tt>&lt;iso646.h&gt;</tt> (D.9.2), <tt>&lt;stdalign.h&gt;</tt> (D.9.3),
<tt>&lt;stdbool.h&gt;</tt> (D.9.4), and <tt>&lt;tgmath.h&gt;</tt> (D.9.5), each
of which has a name of the form <tt>&lt;name.h&gt;</tt>, behaves as if each
name placed in the standard library namespace by the corresponding
<tt>&lt;cname&gt;</tt> header is placed within the global namespace scope,
except for the functions described in 26.8.6, the declaration of
<tt>std::byte</tt> (17.2.1), and the functions and function templates described
in 17.2.5. It is unspecified whether these names are first declared or defined
within namespace scope (6.4.6) of the namespace <tt>std</tt> and are then
injected into the global namespace scope by explicit using-declarations (9.9).
</del></li>
<li><del>
[<i>Example:</i> The header <tt>&lt;cstdlib&gt;</tt> assuredly provides its
declarations and definitions within the namespace <tt>std</tt>. It may also
provide these names within the global namespace. The header
<tt>&lt;stdlib.h&gt;</tt> assuredly provides the same declarations and
definitions within the global namespace, much as in the C Standard. It may also
provide these names within the namespace <tt>std</tt>. <i>&mdash;end
example</i>]
</del></li>
</ol>
</blockquote>


<blockquote class="note">
Revise compatibility note for Annex C.  This wording needs a little more thought.
</blockquote>

<blockquote class="draft_wording">
<h4>C.6.1 Modifications to headers [diff.mods.to.headers]</h4>
<ol>
<li>
For compatibility with the C standard library, the C++ standard library provides the
C headers enumerated in <del>D.9, but their use is deprecated in C++</del>
<ins><b>[c.headers]</b></ins>.
</li>
<li><del>
There are no C++ headers for the C headers <tt>&lt;stdatomic.h&gt;</tt>,
<tt>&lt;stdnoreturn.h&gt;</tt>, and <tt>&lt;threads.h&gt;</tt>, nor are the C
headers themselves part of C++.
</del></li>
<li><del>
The headers <tt>&lt;ccomplex&gt;</tt> (29.5.11) and <tt>&lt;ctgmath&gt;</tt>
(29.9.6), as well as their corresponding C headers <tt>&lt;complex.h&gt;</tt>
and <tt>&lt;tgmath.h&gt;</tt>, do not contain any of the content from the C
standard library and instead merely include other headers from the C++ standard library.
</del></li>
<li><del>
The headers <tt>&lt;ciso646&gt;</tt>, <tt>&lt;cstdalign&gt;</tt> (21.10.4), and
<tt>&lt;cstdbool&gt;</tt> (21.10.3) are meaningless in C++. Use of the C++ headers
<tt>&lt;ccomplex&gt;</tt>,  <tt>&lt;cstdalign&gt;</tt>, <tt>&lt;cstdbool&gt;</tt>, and
<tt>&lt;ctgmath&gt;</tt> is deprecated (D.4).
</del></li>
</ol>
</blockquote>

<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>

<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.10">D.10 Requires paragraph [depr.res.on.required]</a></h3>
<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This style of documentation was deprecated editorially following the
application of a sequence of papers to update each main library clause,
consistently
following the new conventions established by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0788r3">P0788R3</a>
</p>

<p>
As library clauses continue to be deprecated and migrate to Annex D,
use of this deprecated convention will become internally less consistent,
so the strong recommendation is to apply the new tags consistently
through the parts of Annex D that are retained.  The weak recommendation
is to let this term remain until the last clause using it has been
removed (or undeprecated and updated) in a future standard.
</p>


<blockquote class="recommend">
<b>Strong recommendation:</b>
Remove this feature from C++23.
</blockquote>


<blockquote class="draft_wording">
<h4><del>D.10 Requires paragraph [depr.res.on.required]</del></h4>
<ol>
<li><del>
In addition to the elements specified in 16.4.1.4, descriptions of function
semantics may also contain a <i>Requires:</i> element to denote the
preconditions for calling a function.
</del></li>
<li><del>
Violation of any preconditions specified in a function's <i>Requires:</i>
element results in undefined behavior unless the function's <i>Throws:</i>
element specifies throwing an exception when the precondition is violated.
</del></li>
</ol>

<h4>D.11 Relational operators [depr.relops] </h4>
<blockquote class="note">
It is believed that no implementation uses SFINAE to disable the following
overloads, so the most compatible replacement for a <i>Requires</i> clause
is a <i>Mandates</i> clause.
</blockquote>
<ol>
<li>
The header <tt>&lt;utility&gt;</tt> (20.2.1) has the following additions:
</li>

<blockquote><pre>
namespace std::rel_ops {
  template&lt;class T&gt; bool operator!=(const T&amp;, const T&amp;);
  template&lt;class T&gt; bool operator&gt; (const T&amp;, const T&amp;);
  template&lt;class T&gt; bool operator&lt;=(const T&amp;, const T&amp;);
  template&lt;class T&gt; bool operator&gt;=(const T&amp;, const T&amp;);
}
</pre></blockquote>
<li>
To avoid redundant definitions of <tt>operator!=</tt> out of
<tt>operator==</tt> and operators <tt>&gt;</tt>, <tt>&lt;=</tt>, and
<tt>&gt;=</tt> out of <tt>operator&lt;</tt>, the library provides the
following:
</li>


<pre>template&lt;class T&gt; bool operator!=(const T&amp; x, const T&amp; y);</pre>
<li>
<i><del>Requires</del><ins>Mandates</ins>:</i> Type <tt>T</tt> is <i>Cpp17EqualityComparable</i> (Table 23).
</li>
<li>
<i>Returns:</i> <tt>!(x == y)</tt>.
</li>

<pre>template&lt;class T&gt; bool operator&gt;(const T&amp; x, const T&amp; y);</pre>
<li>
<i><del>Requires</del><ins>Mandates</ins>:</i> Type <tt>T</tt> is <i>Cpp17LessThanComparable</i> (Table 24).
</li>
<li>
<i>Returns:</i> <tt>y &lt; x</tt>.
</li>

<pre>template&lt;class T&gt; bool operator&lt;=(const T&amp; x, const T&amp; y);</pre>
<li>
<i><del>Requires</del><ins>Mandates</ins>:</i> Type <tt>T</tt> is <i>Cpp17LessThanComparable</i> (Table 24).
</li>
<li>
<i>Returns:</i> <tt>!(y &lt; x)</tt>.
</li>

<pre>template&lt;class T&gt; bool operator&gt;=(const T&amp; x, const T&amp; y);</pre>
<li>
<i><del>Requires</del><ins>Mandates</ins>:</i> Type <tt>T</tt> is <i>Cpp17LessThanComparable</i> (Table 24).
</li>
<li>
<i>Returns:</i> <tt>!(x &lt; y)</tt>.
</li>

</ol>

<h4>D.13 Deprecated type traits [depr.meta.types]</h4>
<ol>
<li>
The header <tt>&lt;type_traits&gt;</tt> (20.15.2) has the following additions:
</li>
<blockquote><pre>
namespace std {
  template&lt;class T&gt; struct is_pod;
  template&lt;class T&gt; inline constexpr bool is_pod_v = is_pod&lt;T&gt;::value;
}
</pre></blockquote>

<li>
The behavior of a program that adds specializations for any of the templates
defined in this subclause is undefined, unless explicitly permitted by the
specification of the corresponding template.
</li>

<pre>template&lt;class T&gt; struct is_pod;</pre>
<li>
<i><del>Requires</del><ins>Mandates</ins>:</i>
<tt>remove_all_extents_t&lt;T&gt;</tt> shall be a complete type or <i>cv</i> <tt>void</tt>.
</li>

<li>
<i><ins>Remarks:</ins></i>
<tt>is_pod&lt;T&gt;</tt> is a <i>Cpp17UnaryTypeTrait</i> (20.15.1) with a base
characteristic of <tt>true_type</tt> if <tt>T</tt> is a POD type, and
<tt>false_type</tt> otherwise. A POD class is a class that is both a trivial
class and a standard-layout class, and has no non-static data members of type
non-POD class (or array thereof). A POD type is a scalar type, a POD class, an
array of such a type, or a cv-qualified version of one of these types.  </li>

<li>
[<i>Note:</i> It is unspecified whether a closure type (7.5.5.1) is a POD type. <i>&mdash;end note</i>]
</li>
</ol>

<h4>D.18 Deprecated <tt>shared_ptr</tt> atomic access [depr.util.smartptr.shared.atomic]</h4>
<ol>
<li>
The header <tt>&lt;memory&gt;</tt>  (20.10.2) has the following additions:
</li>

<blockquote><pre>
namespace std {
template &lt;class T&gt;
  bool atomic_is_lock_free(const shared_ptr&lt;T&gt;* p);

template &lt;class T&gt;
  shared_ptr&lt;T&gt; atomic_load(const shared_ptr&lt;T&gt;* p);
template &lt;class T&gt;
  shared_ptr&lt;T&gt; atomic_load_explicit(const shared_ptr&lt;T&gt;* p, memory_order mo);

template &lt;class T&gt;
  void atomic_store(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r);
template &lt;class T&gt;
  void atomic_store_explicit(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r, memory_order mo);

template &lt;class T&gt;
  shared_ptr&lt;T&gt; atomic_exchange(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r);
template &lt;class T&gt;
  shared_ptr&lt;T&gt; atomic_exchange_explicit(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r, memory_order mo);

template &lt;class T&gt;
  bool atomic_compare_exchange_weak(
    shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w);
template &lt;class T&gt;
  bool atomic_compare_exchange_strong(
    shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w);
template &lt;class T&gt;
  bool atomic_compare_exchange_weak_explicit(
    shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w,
    memory_order success, memory_order failure);
template &lt;class T&gt;
  bool atomic_compare_exchange_strong_explicit(
    shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w,
    memory_order success, memory_order failure);
}
</pre></blockquote>

<li>
Concurrent access to a <tt>shared_ptr</tt> object from multiple threads does
not introduce a data race if the access is done exclusively via the functions
in this section and the instance is passed as their first argument.
</li>
<li>
The meaning of the arguments of type <tt>memory_order</tt> is explained in 31.4.
</li>

<blockquote><pre>
template&lt;class T&gt;
  bool atomic_is_lock_free(const shared_ptr&lt;T&gt;* p);
</pre></blockquote>
<li>
<i><del>Requires</del><ins>Preconditions</del>:</i> <tt>p</tt> shall not be null.
</li>
<li>
<i>Returns:</i> <tt>true</tt> if atomic access to <tt>*p</tt> is lock-free, <tt>false</tt> otherwise.
</li>
<li>
<i>Throws:</i> Nothing.
</li>

<blockquote><pre>
template&lt;class T&gt;
  shared_ptr&lt;T&gt; atomic_load(const shared_ptr&lt;T&gt;* p);
</pre></blockquote>
<li>
<i><del>Requires</del><ins>Preconditions</del>:</i> <tt>p</tt> shall not be null.
</li>
<li>
<i>Returns:</i> <tt>atomic_load_explicit(p, memory_order::seq_cst)</tt>.
</li>
<li>
<i>Throws:</i> Nothing.
</li>

<blockquote><pre>
template&lt;class T&gt;
  shared_ptr&lt;T&gt; atomic_load_explicit(const shared_ptr&lt;T&gt;* p, memory_order mo);
</pre></blockquote>
<li>
<i><del>Requires</del><ins>Preconditions</del>:</i> <tt>p</tt> shall not be null.
</li>
<li>
<i><del>Requires</del><ins>Preconditions</del>:</i> <tt>mo</tt> shall not be <tt>memory_order::release</tt> or <tt>memory_order::acq_rel</tt>.
</li>
<li>
<i>Returns:</i> <tt>*p</tt>.
</li>
<li>
<i>Throws:</i> Nothing.
</li>

<blockquote><pre>
template&lt;class T&gt;
  void atomic_store(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r);
</pre></blockquote>
<li>
<i><del>Requires</del><ins>Preconditions</del>:</i> <tt>p</tt> shall not be null.
</li>
<li>
<i>Effects:</i> As if by <tt>atomic_store_explicit(p, r, memory_order::seq_cst)</tt>.
</li>
<li>
<i>Throws:</i> Nothing.
</li>

<blockquote><pre>
template&lt;class T&gt;
  void atomic_store_explicit(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r, memory_order mo);
</pre></blockquote>
<li>
<i><del>Requires</del><ins>Preconditions</del>:</i> <tt>p</tt> shall not be null.
</li>
<li>
<i>Requires:</i> <tt>mo</tt> shall not be <tt>memory_order::acquire</tt> or <tt>memory_order::acq_rel</tt>.
</li>
<li>
<i>Effects:</i> As if by <tt>p-&gt;swap(r)</tt>.
</li>
<li>
<i>Throws:</i> Nothing.
</li>

<blockquote><pre>
template&lt;class T&gt;
  shared_ptr&lt;T&gt; atomic_exchange(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r);
</pre></blockquote>
<li>
<i><del>Requires</del><ins>Preconditions</del>:</i> <tt>p</tt> shall not be null.
</li>
<li>
<i>Returns:</i> <tt>atomic_exchange_explicit(p, r, memory_order::seq_cst)</tt>.
</li>
<li>
<i>Throws:</i> Nothing.
</li>

<blockquote><pre>
template&lt;class T&gt;
  shared_ptr&lt;T&gt; atomic_exchange_explicit(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r, memory_order mo);
</pre></blockquote>
<li>
<i><del>Requires</del><ins>Preconditions</del>:</i> <tt>p</tt> shall not be null.
</li>
<li>
<i>Effects:</i> As if by <tt>p-&gt;swap(r)</tt>.
</li>
<li>
<i>Returns:</i> The previous value of <tt>*p</tt>.
</li>
<li>
<i>Throws:</i> Nothing.
</li>

<blockquote><pre>
template&lt;class T&gt;
  bool atomic_compare_exchange_weak(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w);
</pre></blockquote>
<li>
<i><del>Requires</del><ins>Preconditions</del>:</i> <tt>p</tt> shall not be null.
</li>
<li>
<i>Returns:</i>
     <tt>atomic_compare_exchange_weak_explicit(p, v, w, memory_order::seq_cst, memory_order::seq_cst)</tt>.
</li>
<li>
<i>Throws:</i> Nothing.
</li>

<blockquote><pre>
template&lt;class T&gt;
  bool atomic_compare_exchange_strong(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w);
</pre></blockquote>
<li>
<i>Returns:</i>
     <tt>atomic_compare_exchange_strong_explicit(p, v, w, memory_order::seq_cst, memory_order::seq_cst)</tt>.
</li>

<blockquote><pre>
template &lt;class T&gt;
  bool atomic_compare_exchange_weak_explicit(
    shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w,
    memory_order success, memory_order failure);
template &lt;class T&gt;
  bool atomic_compare_exchange_strong_explicit(
    shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w,
    memory_order success, memory_order failure);
</pre></blockquote>
<li>
<i><del>Requires</del><ins>Preconditions</del>:</i> <tt>p</tt> shall not be null and <tt>v</tt> shall not be null.
The <tt>failure</tt> argument shall not be <tt>memory_order::release</tt> nor
<tt>memory_order::acq_rel</tt>.
</li>
<li>
<i>Effects:</i> If <tt>*p</tt> is equivalent to <tt>*v</tt>, assigns <tt>w</tt>
to <tt>*p</tt> and has synchronization semantics corresponding to the value of
<tt>success</tt>, otherwise assigns <tt>*p</tt> to <tt>*v</tt> and has synchronization semantics
corresponding to the value of <tt>failure</tt>.
</li>
<li>
<i>Returns:</i> <tt>true</tt> if <tt>*p</tt> was equivalent to <tt>*v</tt>, <tt>false</tt> otherwise.
</li>
<li>
<i>Throws:</i> Nothing.
</li>
<li>
<i>Remarks:</i> Two <tt>shared_ptr</tt> objects are equivalent if they store
the same pointer value and share ownership. The weak form may fail spuriously.
See 31.8.1.
</li>
</ol>


<h4>D.21 Deprecated convenience conversion interfaces [depr.conversions]</h4>
<h4>D.21.1 Class template wstring_convert [depr.conversions.string]</h4>
<ol>
<li>
Class template <tt>wstring_convert</tt> performs conversions between a wide
string and a byte string.  It lets you specify a code conversion facet (like
class template <tt>codecvt</tt>) to perform the conversions, without affecting
any streams or locales.  [ <i>Example:</i> If you want to use the code
conversion facet <tt>codecvt_utf8</tt> to output to <tt>cout</tt> a UTF-8
multibyte sequence corresponding to a wide string, but you don’t want to alter
the locale for <tt>cout</tt>, you can write something like:
<pre><blockquote>
<ins>std::</ins>wstring_convert&lt;std::codecvt_utf8&lt;wchar_t&gt;&gt; myconv;
std::string mbstring = myconv.to_bytes(L"Hello\n");
std::cout &lt;&lt; mbstring;
</blockquote></pre>
&mdash; <i>end example</i> ]
</li>

<pre><blockquote>
namespace std {
template &lt;class Codecvt, class Elem = wchar_t,
          class WideAlloc = allocator&lt;Elem&gt;,
          class ByteAlloc = allocator&lt;char&gt;&gt;
  class wstring_convert {
  public:
    using byte_string = basic_string&lt;char, char_traits&lt;char&gt;, ByteAlloc&gt;;
    using wide_string = basic_string&lt;Elem, char_traits&lt;Elem&gt;, WideAlloc&gt;;
    using state_type  = typename Codecvt::state_type;
    using int_type    = typename wide_string::traits_type::int_type;

    wstring_convert() : wstring_convert(new Codecvt) {}
    explicit wstring_convert(Codecvt* pcvt = new Codecvt);
    wstring_convert(Codecvt* pcvt, state_type state);
    explicit wstring_convert(const byte_string&amp; byte_err,
                             const wide_string&amp; wide_err = wide_string());
    ~wstring_convert();

    wstring_convert(const wstring_convert&amp;) = delete;
    wstring_convert&amp; operator=(const wstring_convert&amp;) = delete;

    wide_string from_bytes(char byte);
    wide_string from_bytes(const char* ptr);
    wide_string from_bytes(const byte_string&amp; str);
    wide_string from_bytes(const char* first, const char* last);

    byte_string to_bytes(Elem wchar);
    byte_string to_bytes(const Elem* wptr);
    byte_string to_bytes(const wide_string&amp; wstr);
    byte_string to_bytes(const Elem* first, const Elem* last);

    size_t converted() const noexcept;
    state_type state() const;

  private:
    byte_string byte_err_string;  <i>// Exposition only</i>
    wide_string wide_err_string;  <i>// Exposition only</i>
    Codecvt* cvtptr;              <i>// Exposition only</i>
    state_type cvtstate;          <i>// Exposition only</i>
    size_t cvtcount;              <i>// Exposition only</i>
  };
}
</blockquote></pre>

<li>
The class template describes an object that controls conversions between wide
string objects of class
<tt>basic_string&lt;Elem, char_traits&lt;Elem&gt;, WideAlloc&gt;</tt> and
byte string objects of class
<tt>basic_string&lt;char, char_traits&lt;char&gt;, ByteAlloc&gt;</tt>.
The class template defines the types <tt>wide_string</tt> and
<tt>byte_string</tt> as synonyms for these two types. Conversion between a
sequence of <tt>Elem</tt> values (stored in a <tt>wide_string</tt> object) and
multibyte sequences (stored in a <tt>byte_string</tt> object) is performed by
an object of class <tt>Codecvt</tt>, which meets the requirements of the
standard code-conversion facet <tt>codecvt&lt;Elem, char, mbstate_t&gt;</tt>.
</li>
<li>
An object of this class template stores:
  <ol>
  <li>
  &mdash; <tt>byte_err_string</tt> &mdash; a byte string to display on errors
  </li>
  <li>
  &mdash; <tt>wide_err_string</tt> &mdash; a wide string to display on errors
  </li>
  <li>
  &mdash; <tt>cvtptr</tt> &mdash; a pointer to the allocated conversion object
  (which is freed when the <tt>wstring_convert</tt> object is destroyed)
  </li>
  <li>
  &mdash; <tt>cvtstate</tt> &mdash; a conversion state object
  </li>
  <li>
  &mdash; <tt>cvtcount</tt> &mdash; a conversion count
  </li>
  </ol>
</li>

<pre><blockquote>
using byte_string = basic_string&lt;char, char_traits&lt;char&gt;, ByteAlloc&gt;;
</blockquote></pre>
<li>
The type shall be a synonym for
<tt>basic_string&lt;char, char_traits&lt;char&gt;, ByteAlloc&gt;</tt>
</li>

<pre><blockquote>
size_t converted() const noexcept;
</blockquote></pre>
<li>
<i>Returns:</i> <tt>cvtcount</tt>.
</li>

<pre><blockquote>
wide_string from_bytes(char byte);
wide_string from_bytes(const char* ptr);
wide_string from_bytes(const byte_string&amp; str);
wide_string from_bytes(const char* first, const char* last);
</blockquote></pre>
<li>
<i>Effects:</i> The first member function shall convert the single-element
sequence <tt>byte</tt> to a wide string. The second member function shall
convert the null-terminated sequence beginning at <tt>ptr</tt> to a wide
string. The third member function shall convert the sequence stored in str to a
wide string. The fourth member function shall convert the sequence defined by
the range <tt>[first, last)</tt> to a wide string.
</li>
<li>
In all cases:
  <ol>
  <li>
&mdash; If the <tt>cvtstate</tt> object was not constructed with an explicit
value, it shall be set to its default value (the initial conversion state)
before the conversion begins. Otherwise it shall be left unchanged.
  </li>
  <li>
&mdash; The number of input elements successfully converted shall be stored in
<tt>cvtcount</tt>.
  </li>
  </ol>
</li>

<li>
<i>Returns:</i> If no conversion error occurs, the member function shall return
the converted wide string. Otherwise, if the object was constructed with a
wide-error string, the member function shall return the wide-error string.
Otherwise, the member function throws an object of class <tt>range_error</tt>.
</li>

<pre><blockquote>
using int_type = typename wide_string::traits_type::int_type;
</blockquote></pre>
<li>
The type shall be a synonym for <tt>wide_string::traits_type::int_type</tt>.
</li>

<pre><blockquote>
state_type state() const;
</blockquote></pre>
<li>
returns <tt>cvtstate</tt>.
</li>

<pre><blockquote>
using state_type = typename Codecvt::state_type;
</blockquote></pre>
<li>
The type shall be a synonym for <tt>Codecvt::state_type</tt>.
</li>

<pre><blockquote>
byte_string to_bytes(Elem wchar);
byte_string to_bytes(const Elem* wptr);
byte_string to_bytes(const wide_string&amp; wstr);
byte_string to_bytes(const Elem* first, const Elem* last);
</blockquote></pre>
<li>
<i>Effects:</i> The first member function shall convert the single-element
sequence <tt>wchar</tt> to a byte string. The second member function shall
convert the null-terminated sequence beginning at <tt>wptr</tt> to a byte
string. The third member function shall convert the sequence stored in wstr to
a byte string. The fourth member function shall convert the sequence defined by
the range <tt>[first, last)</tt> to a byte string.
</li>

<li>
In all cases:
  <ol>
  <li>
&mdash; If the <tt>cvtstate</tt> object was not constructed with an explicit
value, it shall be set to its default value (the initial conversion state)
before the conversion begins. Otherwise it shall be left unchanged.
  </li>
  <li>
&mdash; The number of input elements successfully converted shall be stored in
<tt>cvtcount</tt>.
  </li>
  </ol>
</li>

<li>
<i>Returns:</i> If no conversion error occurs, the member function shall return
the converted byte string. Otherwise, if the object was constructed with a
byte-error string, the member function shall return the byte-error string.
Otherwise, the member function shall throw an object of class
<tt>range_error</tt>.
</li>

<pre><blockquote>
using wide_string = basic_string&lt;Elem, char_traits&lt;Elem&gt;, WideAlloc&gt;;
</blockquote></pre>
<li>
The type shall be a synonym for
<tt>basic_string&lt;Elem, char_traits&lt;Elem&gt;, WideAlloc&gt;</tt>.
</li>

<pre><blockquote>
explicit wstring_convert(Codecvt* pcvt = new Codecvt);
wstring_convert(Codecvt* pcvt, state_type state);
explicit wstring_convert(const byte_string&amp; byte_err,
    const wide_string&amp; wide_err = wide_string());
</blockquote></pre>
<li>
<i><del>Requires</del><ins>Preconditions</ins>:</i> For the first and second constructors, <tt>pcvt != nullptr</tt>.
</li>

<li>
<i>Effects:</i> The first constructor shall store <tt>pcvt</tt> in
<tt>cvtptr</tt> and default values in <tt>cvtstate</tt>,
<tt>byte_err_string</tt>, and <tt>wide_err_string</tt>. The second constructor
shall store <tt>pcvt</tt> in <tt>cvtptr</tt>, <tt>state</tt> in
<tt>cvtstate</tt>, and default values in <tt>byte_err_string</tt> and
<tt>wide_err_string</tt>; moreover the stored state shall be retained between
calls to <tt>from_bytes</tt> and <tt>to_bytes</tt>. The third constructor shall
store <tt>new Codecvt</tt> in <tt>cvtptr</tt>, <tt>state_type()</tt> in
<tt>cvtstate</tt>, <tt>byte_err</tt> in <tt>byte_err_string</tt>, and
<tt>wide_err</tt> in <tt>wide_err_string</tt>.
</li>

<pre><blockquote>
~wstring_convert();
</blockquote></pre>
<li>
<i>Effects:</i> The destructor shall delete <tt>cvtptr</tt>.
</li>
</ol>


<h4>D.21.2 Class template wbuffer_convert [depr.conversions.buffer]</h4>
<ol>
<li>
Class template <tt>wbuffer_convert</tt> looks like a wide stream buffer, but
performs all its I/O through an underlying byte stream buffer that you specify
when you construct it. Like class template <tt>wstring_convert</tt>, it lets
you specify a code conversion facet to perform the conversions, without
affecting any streams or locales.
</li>
<pre><blockquote>
namespace std {
template &lt;class Codecvt, class Elem = wchar_t, class Tr = char_traits&lt;Elem&gt;&gt;
  class wbuffer_convert
    : public basic_streambuf&lt;Elem, Tr&gt; {
  public:
    using state_type = typename Codecvt::state_type;

    wbuffer_convert() : wbuffer_convert(nullptr) {}
    explicit wbuffer_convert(streambuf* bytebuf = 0,
                             Codecvt* pcvt = new Codecvt,
                             state_type state = state_type());

    ~wbuffer_convert();

    wbuffer_convert(const wbuffer_convert&amp;) = delete;
    wbuffer_convert&amp; operator=(const wbuffer_convert&amp;) = delete;

    streambuf* rdbuf() const;
    streambuf* rdbuf(streambuf* bytebuf);

    state_type state() const;

  private:
    streambuf* bufptr;        // exposition only
    Codecvt* cvtptr;          // exposition only
    state_type cvtstate;      // exposition only
  };
}
</blockquote></pre>
<li>
The class template describes a stream buffer that controls the transmission of
elements of type <tt>Elem</tt>, whose character traits are described by the class <tt>Tr</tt>, to
and from a byte stream buffer of type <tt>streambuf</tt>.  Conversion between a sequence
of <tt>Elem</tt> values and multibyte sequences is performed by an object of class
<tt>Codecvt</tt>, which shall meet the requirements of the standard code-conversion
facet <tt>codecvt&lt;Elem, char, mbstate_t&gt;</tt>.
</li>

<li>
An object of this class template stores:
  <ol>
  <li>
&mdash; <tt>bufptr</tt> &mdash; a pointer to its underlying byte stream buffer
  </li>
  <li>
&mdash; <tt>cvtptr</tt> &mdash; a pointer to the allocated conversion object (which is freed when the <tt>wbuffer_convert</tt> object is destroyed)
  </li>
  <li>
&mdash; <tt>cvtstate</tt> &mdash; a conversion state object
  </li>
  </ol>
</li>

<pre><blockquote>
state_type state() const;
</blockquote></pre>
<li>
<i>Returns:</i> <tt>cvtstate</tt>.
</li>

<pre><blockquote>
streambuf* rdbuf() const;
</blockquote></pre>
</li>
<li>
<i>Returns:</i> <tt>bufptr</tt>.
</li>

<pre><blockquote>
streambuf* rdbuf(streambuf* bytebuf);
</blockquote></pre>
<li>
<i>Effects:</i> Stores <tt>bytebuf</tt> in <tt>bufptr</tt>.
</li>
<li>
<i>Returns:</i> The previous value of <tt>bufptr</tt>.
</li>

<pre><blockquote>
using state_type = typename Codecvt::state_type;
</blockquote></pre>
<li>
The type shall be a synonym for <tt>Codecvt::state_type</tt>.
</li>

<pre><blockquote>
explicit wbuffer_convert(streambuf* bytebuf = 0,
    Codecvt* pcvt = new Codecvt, state_type state = state_type());
</blockquote></pre>
<li>
<i><del>Requires</del><ins>Preconditions</ins>:</i> <tt>pcvt != nullptr</tt>.
</li>
<li>
<i>Effects:</i> The constructor constructs a stream buffer object, initializes
<tt>bufptr</tt> to <tt>bytebuf</tt>, initializes <tt>cvtptr</tt> to
<tt>pcvt</tt>, and initializes <tt>cvtstate</tt> to <tt>state</tt>.
</li>

<pre><blockquote>
~wbuffer_convert();
</blockquote></pre>

<li>
<i>Effects:</i> The destructor shall delete <tt>cvtptr</tt>.
</li>
</ol>


<h4>D.23 Deprecated filesystem path factory functions [depr.fs.path.factory]</h4>
<blockquote class="note">
The <i>Requires</i> clause here covers both compile-time and run-time
condditions, so is split into separate <i>Mandates</i> and
<i>Predconditions</i> clauses.  A drive-by fix further catches that seeral
typedefs intending to refer to members of <tt>path</tt> are actually
meaningless for a non-member factory function.  The current form of wording was
copy/pasted from the specification of constructors where the <tt>path::</tt>
would be implicit.
</blockquote>
<ol>
<li><ins>
The header <tt>&lt;filesystem&gt;</tt> (29.11.5) has the following additions:
</ins></li>
<pre>
template&lt;class Source&gt;
  path u8path(const Source&amp; source);
template&lt;class InputIterator&gt;
  path u8path(InputIterator first, InputIterator last);
</pre>

<li><del>
<i>Requires:</i> 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> or <tt>char8_t</tt>. <tt>Source</tt> meets the requirements
specified in 29.11.7.3.
</del></li>

<li><ins>
<i>Mandates:</i> The value type of <tt>Source</tt> and <tt>InputIterator</tt> is
<tt>char</tt> or <tt>char8_t</tt>. <tt>Source</tt> meets the requirements
specified in 29.11.7.3.
</ins></li>
<li><ins>
<i>Preconditions:</i> The <tt>source</tt> and <tt>[first, last)</tt> sequences are
UTF-8 encoded.
</ins></li>

<li>
<i>Returns:</i>
<ol>
<li>
&mdash; If <tt><ins>path::</ins>value_type</tt> is <tt>char</tt> and the
current native narrow encoding (29.11.7.2.2) is UTF-8, return
<tt>path(source)</tt> or <tt>path(first, last)</tt>; otherwise,
</li>
<li>
&mdash; if <tt><ins>path::</ins>value_type</tt> is <tt>wchar_t</tt> and the
native wide encoding is UTF-16, or if <tt><ins>path::</ins>value_type</tt> is
<tt>char16_t</tt> or <tt>char32_t</tt>, convert <tt>source</tt> or
<tt>[first,last)</tt> to a temporary, <tt>tmp</tt>, of type
<tt><ins>path::</ins>string_type</tt> and return <tt>path(tmp)</tt>; otherwise,
</li>
<li>
— convert <tt>source</tt> or <tt>[first, last)</tt> to a temporary, <tt>tmp</tt>, of type <tt>u32string</tt> and return <tt>path(tmp)</tt>.
</li>
</ol>
<li>
<i>Remarks:</i> Argument format conversion (29.11.7.2.1) applies to the
arguments for these functions. How Unicode encoding conversions are performed
is unspecified.
</li>
<li>
[<i>Example:</i> A string is to be read from a database that is encoded in
UTF-8, and used to create a directory using the native encoding for filenames:
<blockquote><pre>
namespace fs = std::filesystem;
std::string utf8_string = read_utf8_data();
fs::create_directory(fs::u8path(utf8_string));
</pre></blockquote>
For POSIX-based operating systems with the native narrow encoding set to UTF-8,
no encoding or type conversion occurs.
<p>
For POSIX-based operating systems with the native narrow encoding not set to
UTF-8, a conversion to UTF-32 occurs, followed by a conversion to the current
native narrow encoding. Some Unicode characters may have no native character
set representation.
</p>
For Windows-based operating systems a conversion from UTF-8 to UTF-16 occurs.
<i>&mdash;end example</i>] [<i>Note:</i> The example above is representative of
a historical use of <tt>filesystem::u8path</tt>. Passing a
<tt>std::u8string</tt> to <tt>path</tt>’s constructor is preferred for an
indication of UTF-8 encoding more consistent with <tt>path</tt>’s handling of
other encodings. <i>&mdash;end note</i>]
</li>
</ol>

</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>



<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.11">D.11 Relational operators [depr.relops]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This feature was deprecated with the introduction of support for the
3-way comparison &quot;spaceship&quot; operator, by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0768r1">P0768R1</a>.
</p>

<p>
The <tt>std::rel_ops</tt> namespace was introduced in the original C++
standard, so its removal would potentially impact on code written against C++98
and later standards.  However, this paper will still recommend strongly for its
removal from the C++23 standard.  The feature relies on the antipattern of
<tt>using</tt> a namespace in a namespace scope in order to provide comparison
operators for my own type, typically in a header.  Such usage is not
recommended as the <tt>using</tt> will have an impact on code in other headers,
and potentially introduce header order dependencies.  A more targeted use
within a function may serve as an adaption for 3rd party libraries, but again,
by providing these operators for all types whether desired or not.  As there
are no viable base classes in this namespace, it was never possible to arrange
for these operators to be discovered by ADL, so there was no better workaround
to tame these functions.
</p>
<p>
The better solution appeared in C++20 with the introduction of the spaceship
operator, and rules for synthesizing comparisons from a few primitive operators
now built into the language.  The typical remedy for much code will be to
simply remove the offending <tt>using namespace std::rel_ops;</tt> from their
code, and it should continue to work.  As added insurance, the name
<tt>rel_ops</tt> will be added to the list of zombie names reserved for
previous standardization so that standard library vendors can continue to offer
these as a compatibility shim for their customers for as long as they wish, so
the impact on the user community of removing the specification of this feature
from the standard is expected to be minimal.
</p>

<p>
The weak recommendation is that this feature was deprecated just one standard
prior, so the user community may take a while to catch up and remove the
dependencies from their code.  Holding the feature in Annex D does little harm,
but the wording should be updated to the latest library documentation style for
C++23.  We do not see any reason to consider undeprecation of this feature.
</p>


<blockquote class="recommend">
<b>Strong recommendation:</b>
Remove this feature from C++23.
</blockquote>


<blockquote class="draft_wording">
<h4>16.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization:
</li>
<ol>
<li>&mdash; <tt>auto_ptr</tt>,</li>
<li>&mdash; <tt>auto_ptr_ref</tt>,</li>
<li>&mdash; <tt>binary_function</tt>,</li>
<li>&mdash; <tt>binary_negate</tt>,</li>
<li>&mdash; <tt>bind1st</tt>,</li>
<li>&mdash; <tt>bind2nd</tt>,</li>
<li>&mdash; <tt>binder1st</tt>,</li>
<li>&mdash; <tt>binder2nd</tt>,</li>
<li>&mdash; <tt>const_mem_fun1_ref_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun1_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun_ref_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun_t</tt>,</li>
<li>&mdash; <tt>get_temporary_buffer</tt>,</li>
<li>&mdash; <tt>get_unexpected</tt>,</li>
<li>&mdash; <tt>gets</tt>,</li>
<li>&mdash; <tt>is_literal_type</tt>,</li>
<li>&mdash; <tt>is_literal_type_v</tt>,</li>
<li>&mdash; <tt>mem_fun1_ref_t</tt>,</li>
<li>&mdash; <tt>mem_fun1_t</tt>,</li>
<li>&mdash; <tt>mem_fun_ref_t</tt>,</li>
<li>&mdash; <tt>mem_fun_ref</tt>,</li>
<li>&mdash; <tt>mem_fun_t</tt>,</li>
<li>&mdash; <tt>mem_fun</tt>,</li>
<li>&mdash; <tt>not1</tt>,</li>
<li>&mdash; <tt>not2</tt>,</li>
<li>&mdash; <tt>pointer_to_binary_function</tt>,</li>
<li>&mdash; <tt>pointer_to_unary_function</tt>,</li>
<li>&mdash; <tt>ptr_fun</tt>,</li>
<li>&mdash; <tt>random_shuffle</tt>,</li>
<li>&mdash; <tt>raw_storage_iterator</tt>,</li>
<li><ins>&mdash; <tt>rel_ops</tt>,</ins></li>
<li>&mdash; <tt>result_of</tt>,</li>
<li>&mdash; <tt>result_of_t</tt>,</li>
<li>&mdash; <tt>return_temporary_buffer</tt>,</li>
<li>&mdash; <tt>set_unexpected</tt>,</li>
<li>&mdash; <tt>unary_function</tt>,</li>
<li>&mdash; <tt>unary_negate</tt>,</li>
<li>&mdash; <tt>uncaught_exception</tt>,</li>
<li>&mdash; <tt>unexpected</tt>, and</li>
<li>&mdash; <tt>unexpected_handler</tt>.</li>
</ol>
</ol>

<h4><del>D.11 Relational operators [depr.relops] </del></h4>
<ol>
<li><del>
The header <tt>&lt;utility&gt;</tt> (20.2.1) has the following additions:
</del></li>

<blockquote><pre>
<del>>namespace std::rel_ops {</del>
  <del>template&lt;class T&gt; bool operator!=(const T&amp;, const T&amp;);</del>
  <del>template&lt;class T&gt; bool operator&gt; (const T&amp;, const T&amp;);</del>
  <del>template&lt;class T&gt; bool operator&lt;=(const T&amp;, const T&amp;);</del>
  <del>template&lt;class T&gt; bool operator&gt;=(const T&amp;, const T&amp;);</del>
<del>>}</del>
</pre></blockquote>
<li><del>
To avoid redundant definitions of <tt>operator!=</tt> out of
<tt>operator==</tt> and operators <tt>&gt;</tt>, <tt>&lt;=</tt>, and
<tt>&gt;=</tt> out of <tt>operator&lt;</tt>, the library provides the
following:
</del></li>

<pre><del>template&lt;class T&gt; bool operator!=(const T&amp; x, const T&amp; y);</del></pre>
<li><del>
<i>Requires:</i> Type <tt>T</tt> is <i>Cpp17EqualityComparable</i> (Table 23).
</del></li>
<li><del>
<i>Returns:</i> <tt>!(x == y)</tt>.
</del></li>

<pre><del>template&lt;class T&gt; bool operator&gt;(const T&amp; x, const T&amp; y);</del></pre>
<li><del>
<i>Requires:</i> Type <tt>T</tt> is <i>Cpp17LessThanComparable</i> (Table 24).
</del></li>
<li><del>
<i>Returns:</i> <tt>y &lt; x</tt>.
</del></li>

<pre><del>template&lt;class T&gt; bool operator&lt;=(const T&amp; x, const T&amp; y);</del></pre>
<li><del>
<i>Requires:</i> Type <tt>T</tt> is <i>Cpp17LessThanComparable</i> (Table 24).
</li><del>
<li><del>
<i>Returns:</i> <tt>!(y &lt; x)</tt>.
</del></li>

<pre><del>template&lt;class T&gt; bool operator&gt;=(const T&amp; x, const T&amp; y);</del></pre>
<li><del>
<i>Requires:</i> Type <tt>T</tt> is <i>Cpp17LessThanComparable</i> (Table 24).
</del></li>
<li><del>
<i>Returns:</i> <tt>!(x &lt; y)</tt>.
</del></li>
</ol>
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Clean up wording.
</blockquote>

<blockquote class="note">
Update wording to replace <i>Requires</i> clauses (see <a href="#3.10">D.10 Requires paragraph</a>).
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.12">D.12 <tt>char*</tt> streams [depr.str.strstreams]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++98
</blockquote>

<p>
The <tt>char*</tt> streams were provided, pre-deprecated, in C++98 and
have been considered for removal before.  The underlying principle of
not removing them until a suitable replacement is available still holds,
so there should be nothing further to discuss at this point.
</p>
<p>
However, it should be noted that the <tt>spanstream</tt> library
passed LEWG review for C++20, but ran out of LWG working time to
integrate into the final standard.  This library is expected to be
the replacement facility we point users to in the future, so it
may be reasonable to again consider the classic strstreams facility
for removal in C++26.
</p>
<p>
There remains the alternative position that this facility has been a
supported shipping part of the C++ standard for around 25 years when
C++23 ships.  If we have not made serious moves to remove the library
in all that time, maybe we should consider undeprecating, and taking
away the shadow of doubt over any code that reaches for this facility
today.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Undeprecate the <tt>char*</tt> streams.
</blockquote>

<blockquote class="note">
Wording to follow on demand, moving subclause D.6 into clause 29.
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.13">D.13 Deprecated type traits [depr.meta.types]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
<p>
While traits have been deprecated in earlier versions of the standard,
C++20 removed all traits deprecated in C++17 and earlier, so the traits
that remain were all deprecated by C++20.
</p>
</blockquote>

<p>
The <tt>is_pod</tt> trait was deprecated by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0767r1">P0767R1</a> 
as part of removing the POD vocabulary from the C++ standard, both core and
library.  The term had changed meaning so frequently that it no longer served
as useful vocabulary.  The type trait was extracted to Annex D, and now itself
provides the only definition in the standard for a POD.  Client code is
encouraged to use the more specific traits for trivial and standard layout
types to better describe their need.
</p>

<p>
The <tt>is_pod</tt> trait was first supplied as part of C++11, so its
removal would potentially impact programs written against the C++11
standard or later.  Users have had up to three years of implementations
warning on use of the deprecated trait, so we could consider removal,
with the usual proviso that the name is preserved as a zombie for
previous standardization.  As the case for removal is not urgent,
the weak recommendation of this paper is to remove the trait from C++23.
</p>

<p>
However, the current wording does not follow library best practices, and should
be updated to better specify the <i>Requires</i> clauses with our modern
vocabulary.  The strong recommendation is to retain it as deprecated in Annex D
and revise the wording accordingly.
<p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
Clean up wording.
</blockquote>

<blockquote class="note">
Update wording to replace <i>Requires</i> clauses (see <a href="#3.10">D.10 Requires paragraph</a>).
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Remove the traits that can live on as zombies.
</blockquote>

<blockquote class="draft_wording">
<h4>16.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization:
</li>
<ol>
<li>&mdash; <tt>auto_ptr</tt>,</li>
<li>&mdash; <tt>auto_ptr_ref</tt>,</li>
<li>&mdash; <tt>binary_function</tt>,</li>
<li>&mdash; <tt>binary_negate</tt>,</li>
<li>&mdash; <tt>bind1st</tt>,</li>
<li>&mdash; <tt>bind2nd</tt>,</li>
<li>&mdash; <tt>binder1st</tt>,</li>
<li>&mdash; <tt>binder2nd</tt>,</li>
<li>&mdash; <tt>const_mem_fun1_ref_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun1_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun_ref_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun_t</tt>,</li>
<li>&mdash; <tt>get_temporary_buffer</tt>,</li>
<li>&mdash; <tt>get_unexpected</tt>,</li>
<li>&mdash; <tt>gets</tt>,</li>
<li>&mdash; <tt>is_literal_type</tt>,</li>
<li>&mdash; <tt>is_literal_type_v</tt>,</li>
<li><ins>&mdash; <tt>is_pod</tt>,</ins></li>
<li><ins>&mdash; <tt>is_pod_v</tt>,</ins></li>
<li>&mdash; <tt>mem_fun1_ref_t</tt>,</li>
<li>&mdash; <tt>mem_fun1_t</tt>,</li>
<li>&mdash; <tt>mem_fun_ref_t</tt>,</li>
<li>&mdash; <tt>mem_fun_ref</tt>,</li>
<li>&mdash; <tt>mem_fun_t</tt>,</li>
<li>&mdash; <tt>mem_fun</tt>,</li>
<li>&mdash; <tt>not1</tt>,</li>
<li>&mdash; <tt>not2</tt>,</li>
<li>&mdash; <tt>pointer_to_binary_function</tt>,</li>
<li>&mdash; <tt>pointer_to_unary_function</tt>,</li>
<li>&mdash; <tt>ptr_fun</tt>,</li>
<li>&mdash; <tt>random_shuffle</tt>,</li>
<li>&mdash; <tt>raw_storage_iterator</tt>,</li>
<li>&mdash; <tt>result_of</tt>,</li>
<li>&mdash; <tt>result_of_t</tt>,</li>
<li>&mdash; <tt>return_temporary_buffer</tt>,</li>
<li>&mdash; <tt>set_unexpected</tt>,</li>
<li>&mdash; <tt>unary_function</tt>,</li>
<li>&mdash; <tt>unary_negate</tt>,</li>
<li>&mdash; <tt>uncaught_exception</tt>,</li>
<li>&mdash; <tt>unexpected</tt>, and</li>
<li>&mdash; <tt>unexpected_handler</tt>.</li>
</ol>
</ol>

<h4><del>D.13 Deprecated Type Traits [depr.meta.type]</del></h4>
<ol>
<li><del>
The header <tt>&lt;type_traits&gt;</tt> (20.15.2) has the following additions:
</del></li>
<blockquote><pre>
<del>namespace std {</del>
  <del>template&lt;class T&gt; struct is_pod;</del>
  <del>template&lt;class T&gt; inline constexpr bool is_pod_v = is_pod&lt;T&gt;::value;</del>
<del>}</del>
</pre></blockquote>

<li><del>
The behavior of a program that adds specializations for any of the templates
defined in this subclause is undefined, unless explicitly permitted by the
specification of the corresponding template.
</del></li>

<pre><del>template&lt;class T&gt; struct is_pod;</del></pre>
<li><del>
<i>Requires:</i>
<tt>remove_all_extents_t&lt;T&gt;</tt> shall be a complete type or <i>cv</i> <tt>void</tt>.
</del></li>

<li><del>
<tt>is_pod&lt;T&gt;</tt> is a <i>Cpp17UnaryTypeTrait</i> (20.15.1) with a base
characteristic of <tt>true_type</tt> if <tt>T</tt> is a POD type, and
<tt>false_type</tt> otherwise. A POD class is a class that is both a trivial
class and a standard-layout class, and has no non-static data members of type
non-POD class (or array thereof). A POD type is a scalar type, a POD class, an
array of such a type, or a cv-qualified version of one of these types.  </li>

<li><del>
[<i>Note:</i> It is unspecified whether a closure type (7.5.5.1) is a POD type. <i>&mdash;end note</i>]
</del></li>
</ol>

</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>

<blockquote class="review_note">
There is a preference for removing replaced facilities from the standard
at the earliest opportunity, and letting the vendors remove the zombie
implementations at a time of their own choosing, assessing their own
customer demand.
</blockquote>



<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.14">D.14 Tuple [depr.tuple]</a></h3>


<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This feature was deprecated as part of the effort to cleanly introduce modules
into the language, and was adopted by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1831r1">P1831R1</a>.
It potentially impacts on code written against C++11 and later standards.
</p>

<p>
This feature was deprecated only at the final meeting of the C++20 development cycle,
and at the time this paper is written, there is no experience with how much code has
been impacted by this deprecation.  As such, it is too early to make any recommendation
for a change with respect to this feature.
</p>

<p>
It is further noted that there is a coupling between the deprecated tuple traits API,
and the deprecated support for volatile structured bindings (D.5).  First, note that
<tt>volatile tuple</tt> itself does not support structured bindings (nor do any
<tt>pair</tt> and <tt>array</tt>) as there are no overloads for the <tt>get</tt>
function taking references to <tt>volatile</tt> qualified objects.  However, it is
still possible for a user to customize their own type to support such <tt>get</tt>
calls.  If we remove the <tt>volatile</tt> support from the tuple traits by default,
then the user would have to provide their own specializations for
<tt>tuple_size&lt;volatile TYPE&gt;</tt> and <tt>tuple_element&lt;volatile TYPE&gt;</tt>,
and similarly for the <tt>const volatile</tt> qualifier.  Alternatively, we could
ensure we remove the deprecated support for <tt>volatile</tt> structured bindings
at the same time that we remove the tuple traits <tt>volatile</tt> API.
</p>


<blockquote class="recommend">
<b>Strong recommendation:</b>
take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>



<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.15">D.15 Variant [depr.variant]</a></h3>


<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This feature was deprecated as part of the effort to cleanly introduce modules
into the language, and was adopted by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1831r1">P1831R1</a>.
It potentially impacts on code written against C++17 and later standards.
</p>

<p>
This feature was deprecated only at the final meeting of the C++20 development
cycle, and at the time this paper is written, there is no experience with how
much code has been impacted by this deprecation. However, <tt>variant</tt> has
been in the language for a much shorter time than the similarly impacted
<tt>tuple</tt>, and so it is likely that much less code would be impacted by
its removal.  Secondly, as <tt>variant</tt> has no <tt>volatile</tt> qualified
member functions, nor external accessors like <tt>get</tt> accepting
<tt>volatile</tt> variants, the scope for reasonable use of a <tt>volatile</tt>
variant is vanishingly small.  Therefore, the strong recommendation of this
paper is to remove directly from C++23, and the weak recommendation is to hold
it over for one more standard cycle, allowing more time for any vestigial usage
to be reworked.
</p>


</p>
<blockquote class="recommend">
<b>Strong recommendation:</b>
remove this feature from C++23.
</blockquote>

<blockquote class="draft_wording">

<h4><del>D.15 Variant [depr.variant]</del></h4>
<ol>
<li><del>
The header <tt>&lt;variant&gt;</tt> (20.7.2) has the following additions:
</del>
<pre>
<del>namespace std {</del>
  <del>template&lt;class T&gt; struct variant_size&lt;volatile T&gt;;</del>
  <del>template&lt;class T&gt; struct variant_size&lt;const volatile T&gt;;</del>
  <del>template&lt;size_t I, class T&gt; struct variant_alternative&lt;I, volatile T&gt;;</del>
  <del>template&lt;size_t I, class T&gt; struct variant_alternative&lt;I, const volatile T&gt;;</del>
<del>}</del>
</pre>
</li>
<pre>
<del>template&lt;class T&gt; class variant_size&lt;volatile T&gt;;</del>
<del>template&lt;class T&gt; class variant_size&lt;const volatile T&gt;;</del>
</pre>
<li><del>
Let <tt>VS</tt> denote <tt>variant_size&lt;T&gt;</tt> of the cv-unqualified type
<tt>T</tt>. Then specializations of each of the two templates meet the
<i>Cpp17UnaryTypeTrait</i> requirements with a base characteristic of
<tt>integral_constant&lt;size_t, VS::value&gt;</tt>.
</del></li>
<pre>
<del>template&lt;size_t I, class T&gt; class variant_alternative&lt;I, volatile T&gt;;</del>
<del>template&lt;size_t I, class T&gt; class variant_alternative&lt;I, const volatile T&gt;;</del>
</pre>
<li><del>
Let <tt>VA</tt> denote <tt>variant_alternative&lt;I, T&gt;</tt> of the cv-unqualified type <tt>T</tt>.
Then specializations of each of the two templates meet the
<i>Cpp17TransformationTrait</i> requirements with a member typedef type that names the
following type: 
  <ol>
  <li><del>
&mdash; for the first specialization, <tt>add_volatile_t&lt;VA::type&gt;</tt>, and
  </li>
  <li><del>
&mdash; for the second specialization, <tt>add_cv_t&lt;VA::type&gt;</tt>. 
  </li>
  </ol>
</del></li>
</ol>

</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>



<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.16">D.16 Deprecated iterator primitives [depr.iterator.primitives]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++17
</blockquote>

<p>
The class template <tt>iterator</tt> was first deprecated in C++17 by the paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0174r0">P0174R2</a>.
The concern was that providing the needed support for iterator typenames
through a templated base class, determining which name maps to which
type purely by parameter order, was less clear than simply providing
the needed names.  Further, there were corner cases in usage that fell
out of template syntax that made this tool hard to recommend as a
simpler way of providing the type names, yet that was its whole reason
to exist.
</p>
<p>
When this facility was reviewed for removal in C++20, it was noted that
there were valid uses that relied on the default template arguments to
deduce at least a few of the needed type names.  Subsequent work on
iterators and ranges in C++20 now means that work is also done by the
primary <tt>iterator_traits</tt> template, and so the remaining use
case (for new code) is also covered, making this class template strictly
redundant.
</p>
<p>
The main concern that remains is breaking old code by removing this
code from the standard libraries.  That risk is ameliorated by the
zombie names clause in the standard, allowing vendors to maintain
their own support for as long as their customers demand.  By the time
C++23 ships, those customers will already have been on 6 years notice
that their code might not be supported in future standards.  However,
we note the repeated use of the name <tt>iterator</tt> as a type
within many containers means we might choose to leave this name off
the zombie list.  We conservatively place it there anyway, to ensure
that we are covered by the previous standardization terminology to
encompass uses other than as a container iterator typedef.
</p>

<p>
The strong recommendation of this paper is to remove this feature from
the pending standard.  The weak recommendation is to ask what further
changes we would like to see before we could remove this feature.  If
there is no anticipated change of circumstance that would allow the
standard to stop tracking this feature, then the recommendation should
be to undeprecate, and restore this text to the main body of the
standard.
</p>

</p>
<blockquote class="recommend">
<b>Strong recommendation:</b>
remove this feature from C++23.
</blockquote>

<blockquote class="draft_wording">
<h4>16.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization:
</li>
<ol>
<li>&mdash; <tt>auto_ptr</tt>,</li>
<li>&mdash; <tt>auto_ptr_ref</tt>,</li>
<li>&mdash; <tt>binary_function</tt>,</li>
<li>&mdash; <tt>binary_negate</tt>,</li>
<li>&mdash; <tt>bind1st</tt>,</li>
<li>&mdash; <tt>bind2nd</tt>,</li>
<li>&mdash; <tt>binder1st</tt>,</li>
<li>&mdash; <tt>binder2nd</tt>,</li>
<li>&mdash; <tt>const_mem_fun1_ref_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun1_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun_ref_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun_t</tt>,</li>
<li>&mdash; <tt>get_temporary_buffer</tt>,</li>
<li>&mdash; <tt>get_unexpected</tt>,</li>
<li>&mdash; <tt>gets</tt>,</li>
<li>&mdash; <tt>is_literal_type</tt>,</li>
<li>&mdash; <tt>is_literal_type_v</tt>,</li>
<li><ins>&mdash; <tt>iterator</tt>,</ins></li>
<li>&mdash; <tt>mem_fun1_ref_t</tt>,</li>
<li>&mdash; <tt>mem_fun1_t</tt>,</li>
<li>&mdash; <tt>mem_fun_ref_t</tt>,</li>
<li>&mdash; <tt>mem_fun_ref</tt>,</li>
<li>&mdash; <tt>mem_fun_t</tt>,</li>
<li>&mdash; <tt>mem_fun</tt>,</li>
<li>&mdash; <tt>not1</tt>,</li>
<li>&mdash; <tt>not2</tt>,</li>
<li>&mdash; <tt>pointer_to_binary_function</tt>,</li>
<li>&mdash; <tt>pointer_to_unary_function</tt>,</li>
<li>&mdash; <tt>ptr_fun</tt>,</li>
<li>&mdash; <tt>random_shuffle</tt>,</li>
<li>&mdash; <tt>raw_storage_iterator</tt>,</li>
<li>&mdash; <tt>result_of</tt>,</li>
<li>&mdash; <tt>result_of_t</tt>,</li>
<li>&mdash; <tt>return_temporary_buffer</tt>,</li>
<li>&mdash; <tt>set_unexpected</tt>,</li>
<li>&mdash; <tt>unary_function</tt>,</li>
<li>&mdash; <tt>unary_negate</tt>,</li>
<li>&mdash; <tt>uncaught_exception</tt>,</li>
<li>&mdash; <tt>unexpected</tt>, and</li>
<li>&mdash; <tt>unexpected_handler</tt>.</li>
</ol>

</ol>


<h4><del>D.16 Deprecated iterator primitives [depr.iterator.primitives]</del></h4>
<h4><del>D.16.1 Basic iterator [depr.iterator.basic]</del></h4>
<ol>
<li><del>
The header <tt>&lt;iterator&gt;</tt> (23.2) has the following addition:</del>
</del></li>
<blockquote><pre>
<del>namespace std {</del>
  <del>template&lt;class Category, class T, class Distance = ptrdiff_t,</del>
    <del>class Pointer = T*, class Reference = T&amp;&gt;</del>
  <del>struct iterator {</del>
    <del>using iterator_category = Category;</del>
    <del>using value_type        = T;</del>
    <del>using difference_type   = Distance;</del>
    <del>using pointer           = Pointer;</del>
    <del>using reference         = Reference;</del>
  <del>};</del>
<del>}</del>
</pre></blockquote>

<li><del>
The <tt>iterator</tt> template may be used as a base class to ease the
definition of required types for new iterators.
</del></li>

<li><del>
[ <i>Note:</i> If the new iterator type is a class template, then these
aliases will not be visible from within the iterator class's template
definition, but only to callers of that class <i>- end note</i>]
</del></li>

<li><del>
[ <i>Example:</i> If a C++ program wants to define a bidirectional iterator for
some data structure containing <tt>double</tt> and such that it works on a large
memory model of the implementation, it can do so with:
<pre>
<del>class MyIterator :</del>
  <del>public iterator&lt;bidirectional_iterator_tag, double, long, T*, T&amp;&gt; {</del>
  <del><i>// code implementing ++, etc.</i></del>
<del>};</del>
</pre>
&mdash; <i>end example</i> ]
</del></li>
</ol>

</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>

<blockquote class="recommend">
<b>Weak recommendation:</b>
Undeprecate the facility, and restore it to clause 23.
</blockquote>

<blockquote class="note">
Wording to be supplied.
</blockquote>

<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.17">D.17 Deprecated <tt>move_iterator</tt> access [depr.move.iter.elem]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This feature was deprecated for C++20 by the paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1252r2">P1252R2</a>
highlighting the concern that for a move iterator adapter, intending to expose
its target as an rvalue (or xvalue), the arrow operator must return the original
adapted iterator, which will likely produce an lvalue when dereferenced.  The
operator is not fit for purpose, and cannot be fixed.  The workaround for users
is to dereference the move iterator with <tt>operator *</tt> and call the member
they wish to access using the familiar <tt>.</tt> notation.  This preserves the
value category of the iterator's target.
</p>

<p>
The proposal for C++20 was to deprecate this operator, with a view to
removal at a later date.  While it may seem early, this is the first
such later date appropriate to consider that removal.
</p>

<p>
Lacking clear evidence that this issue is causing widespread bugs in
practice, the strong recommendation for this paper is to hold the
feature in Annex D for another standard cycle, and strongly consider
its removal in C++23.  The weak recommendation is that with three
years (or more) experience of deprecation warnings, we have given
users enough notice, and it is time to remove this misleading feature
now, from C++23.  Code written against the C++11 standard or later
might be impacted by this change.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
Take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Remove this feature from C++23
</blockquote>

<blockquote class="draft_wording">
<h4><del>D.17 Deprecated move_iterator access [depr.move.iter.elem]</del></h4>
<ol>
<li>
<del>
The following member is declared in addition to those members specified in 23.5.3.5:
</del>
<blockquote><pre>
<del>namespace std {</del>
  <del>template&lt;class Iterator&gt;</del>
    <del>class move_iterator {</del>
    <del>public:</del>
      <del>constexpr pointer operator-&gt;() const;</del>
  <del>};</del>
<del>}</del>
</pre></blockquote>
</li>

<pre><del>constexpr pointer operator-&gt;() const;</del></pre>
<li><del>
<i>Returns:</i> <tt>current</tt>.
</del></li>
</ol>
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.18">D.18 Deprecated <tt>shared_ptr</tt> atomic access [depr.util.smartptr.shared.atomic]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
The legacy C-style atomic API for manipulating shared pointers provided in
C++11 is subtle, frequently misunderstood: a <tt>shared_ptr</tt> that is to
be used with the atomic API can never be used directly, but can only be
manipulated through the atomic API (other than construction and destruction).
Its failure mode on misuse is silent undefined behavior, typically a data
race. 
</p>
<p>
C++20 provides a type-safe alternative that also provides support for
<tt>atomic&lt;weak_ptr&lt;T&gt;&gt;</tt>.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
Remove this feature at the earliest opportunity, ideally C++23.
</blockquote>

<blockquote class="draft_wording">
<h4><del>D.18 Deprecated <tt>shared_ptr</tt> atomic access [depr.util.smartptr.shared.atomic]</del></h4>
<ol>
<li><del>
The header <tt>&lt;memory&gt;</tt>  (20.10.2) has the following additions:
</del></li>

<blockquote><pre>
<del>namespace std {</del>
<del>template &lt;class T&gt;</del>
  <del>bool atomic_is_lock_free(const shared_ptr&lt;T&gt;* p);</del>

<del>template &lt;class T&gt;</del>
  <del>shared_ptr&lt;T&gt; atomic_load(const shared_ptr&lt;T&gt;* p);</del>
<del>template &lt;class T&gt;</del>
  <del>shared_ptr&lt;T&gt; atomic_load_explicit(const shared_ptr&lt;T&gt;* p, memory_order mo);</del>

<del>template &lt;class T&gt;</del>
  <del>void atomic_store(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r);</del>
<del>template &lt;class T&gt;</del>
  <del>void atomic_store_explicit(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r, memory_order mo);</del>

<del>template &lt;class T&gt;</del>
  <del>shared_ptr&lt;T&gt; atomic_exchange(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r);</del>
<del>template &lt;class T&gt;</del>
  <del>shared_ptr&lt;T&gt; atomic_exchange_explicit(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r, memory_order mo);</del>

<del>template &lt;class T&gt;</del>
  <del>bool atomic_compare_exchange_weak(</del>
    <del>shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w);</del>
<del>template &lt;class T&gt;</del>
  <del>bool atomic_compare_exchange_strong(</del>
    <del>shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w);</del>
<del>template &lt;class T&gt;</del>
  <del>bool atomic_compare_exchange_weak_explicit(</del>
    <del>shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w,</del>
    <del>memory_order success, memory_order failure);</del>
<del>template &lt;class T&gt;</del>
  <del>bool atomic_compare_exchange_strong_explicit(</del>
    <del>shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w,</del>
    <del>memory_order success, memory_order failure);</del>
<del>}</del>
</pre></blockquote>

<li><del>
Concurrent access to a <tt>shared_ptr</tt> object from multiple threads does
not introduce a data race if the access is done exclusively via the functions
in this section and the instance is passed as their first argument.
</del></li>
<li><del>
The meaning of the arguments of type <tt>memory_order</tt> is explained in 31.4.
</del></li>

<blockquote><pre>
<del>template&lt;class T&gt;</del>
  <del>bool atomic_is_lock_free(const shared_ptr&lt;T&gt;* p);</del>
</pre></blockquote>
<li><del>
<i>Requires:</i> <tt>p</tt> shall not be null.
</del></li>
<li><del>
<i>Returns:</i> <tt>true</tt> if atomic access to <tt>*p</tt> is lock-free, <tt>false</tt> otherwise.
</del></li>
<li><del>
<i>Throws:</i> Nothing.
</del></li>

<blockquote><pre>
<del>template&lt;class T&gt;</del>
  <del>shared_ptr&lt;T&gt; atomic_load(const shared_ptr&lt;T&gt;* p);</del>
</pre></blockquote>
<li><del>
<i>Requires:</i> <tt>p</tt> shall not be null.
</del></li>
<li><del>
<i>Returns:</i> <tt>atomic_load_explicit(p, memory_order::seq_cst)</tt>.
</del></li>
<li><del>
<i>Throws:</i> Nothing.
</del></li>

<blockquote><pre>
<del>template&lt;class T&gt;</del>
  <del>shared_ptr&lt;T&gt; atomic_load_explicit(const shared_ptr&lt;T&gt;* p, memory_order mo);</del>
</pre></blockquote>
<li><del>
<i>Requires:</i> <tt>p</tt> shall not be null.
</del></li>
<li><del>
<i>Requires:</i> <tt>mo</tt> shall not be <tt>memory_order::release</tt> or <tt>memory_order::acq_rel</tt>.
</del></li>
<li><del>
<i>Returns:</i> <tt>*p</tt>.
</del></li>
<li><del>
<i>Throws:</i> Nothing.
</del></li>

<blockquote><pre>
<del>template&lt;class T&gt;</del>
  <del>void atomic_store(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r);</del>
</pre></blockquote>
<li><del>
<i>Requires:</i> <tt>p</tt> shall not be null.
</del></li>
<li><del>
<i>Effects:</i> As if by <tt>atomic_store_explicit(p, r, memory_order::seq_cst)</tt>.
</del></li>
<li><del>
<i>Throws:</i> Nothing.
</del></li>

<blockquote><pre>
<del>template&lt;class T&gt;</del>
  <del>void atomic_store_explicit(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r, memory_order mo);</del>
</pre></blockquote>
<li><del>
<i>Requires:</i> <tt>p</tt> shall not be null.
</del></li>
<li><del>
<i>Requires:</i> <tt>mo</tt> shall not be <tt>memory_order::acquire</tt> or <tt>memory_order::acq_rel</tt>.
</del></li>
<li><del>
<i>Effects:</i> As if by <tt>p-&gt;swap(r)</tt>.
</del></li>
<li><del>
<i>Throws:</i> Nothing.
</del></li>

<blockquote><pre>
<del>template&lt;class T&gt;</del>
  <del>shared_ptr&lt;T&gt; atomic_exchange(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r);</del>
</pre></blockquote>
<li><del>
<i>Requires:</i> <tt>p</tt> shall not be null.
</del></li>
<li><del>
<i>Returns:</i> <tt>atomic_exchange_explicit(p, r, memory_order::seq_cst)</tt>.
</del></li>
<li><del>
<i>Throws:</i> Nothing.
</del></li>

<blockquote><pre>
<del>template&lt;class T&gt;</del>
  <del>shared_ptr&lt;T&gt; atomic_exchange_explicit(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt; r, memory_order mo);</del>
</pre></blockquote>
<li><del>
<i>Requires:</i> <tt>p</tt> shall not be null.
</del></li>
<li><del>
<i>Effects:</i> As if by <tt>p-&gt;swap(r)</tt>.
</del></li>
<li><del>
<i>Returns:</i> The previous value of <tt>*p</tt>.
</del></li>
<li><del>
<i>Throws:</i> Nothing.
</del></li>

<blockquote><pre>
<del>template&lt;class T&gt;</del>
  <del>bool atomic_compare_exchange_weak(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w);</del>
</pre></blockquote>
<li><del>
<i>Requires:</i> <tt>p</tt> shall not be null.
</del></li>
<li><del>
<i>Returns:</i>
     <tt>atomic_compare_exchange_weak_explicit(p, v, w, memory_order::seq_cst, memory_order::seq_cst)</tt>.
</del></li>
<li><del>
<i>Throws:</i> Nothing.
</del></li>

<blockquote><pre>
<del>template&lt;class T&gt;</del>
  <del>bool atomic_compare_exchange_strong(shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w);</del>
</pre></blockquote>
<li><del>
<i>Returns:</i>
     <tt>atomic_compare_exchange_strong_explicit(p, v, w, memory_order::seq_cst, memory_order::seq_cst)</tt>.
</del></li>

<blockquote><pre>
<del>template &lt;class T&gt;</del>
  <del>bool atomic_compare_exchange_weak_explicit(</del>
    <del>shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w,</del>
    <del>memory_order success, memory_order failure);</del>
<del>template &lt;class T&gt;</del>
  <del>bool atomic_compare_exchange_strong_explicit(</del>
    <del>shared_ptr&lt;T&gt;* p, shared_ptr&lt;T&gt;* v, shared_ptr&lt;T&gt; w,</del>
    <del>memory_order success, memory_order failure);</del>
</pre></blockquote>
<li><del>
<i>Requires:</i> <tt>p</tt> shall not be null and <tt>v</tt> shall not be null.
The <tt>failure</tt> argument shall not be <tt>memory_order::release</tt> nor
<tt>memory_order::acq_rel</tt>.
</del></li>
<li><del>
<i>Effects:</i> If <tt>*p</tt> is equivalent to <tt>*v</tt>, assigns <tt>w</tt>
to <tt>*p</tt> and has synchronization semantics corresponding to the value of
<tt>success</tt>, otherwise assigns <tt>*p</tt> to <tt>*v</tt> and has synchronization semantics
corresponding to the value of <tt>failure</tt>.
</del></li>
<li><del>
<i>Returns:</i> <tt>true</tt> if <tt>*p</tt> was equivalent to <tt>*v</tt>, <tt>false</tt> otherwise.
</del></li>
<li><del>
<i>Throws:</i> Nothing.
</del></li>
<li><del>
<i>Remarks:</i> Two <tt>shared_ptr</tt> objects are equivalent if they store
the same pointer value and share ownership. The weak form may fail spuriously.
See 31.8.1.
</del></li>
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Remove this feature at the earliest opportunity <i>after</i> C++23.
</blockquote>

<blockquote class="note">
Update wording to replace <i>Requires</i> clauses (see <a href="#3.10">D.10 Requires paragraph</a>).
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.19">D.19 Deprecated <tt>basic_string</tt> capacity [depr.string.capacity]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This feature was first deprecated for C++20 by the paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0966r1">P0966R1</a>.
The deprecation was a consequence of cleaning up the behavior of the
<tt>reserve</tt> function to no longer optionally reallocate on a
request to shrink.  The original C++98 specification for
<tt>basic_string</tt> supplied a default argument of 0 for
<tt>reserve</tt>, turning a call to <tt>reserve()</tt> into a
non-binding <tt>shrink_to_fit</tt> request.  Note that
<tt>shrink_to_fit</tt> was added in C++11 to better support this
use case.  With the removal of the potentially reallocating
behavior, <tt>reserve()</tt> is now a redundant function overload
that is guaranteed to do nothing.  Hence it was deprecated in
C++20, with a view to removing it entirely in a later standard to
eliminate on more legacy source of confusion from the standard.
</p>

<p>
As the feature was deprecated so recently, the strong recommendation
of this paper is to make no changes for C++23, but strongly consider
removal when it is time to review again for C++26.  The weak
recommendation is that this feature is small and obscure enough that
it is better to remove now from C++23 than preserve for another
three years into C++26.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
Take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Remove this feature from C++23
</blockquote>

<blockquote class="draft_wording">
<h4><del>D.19 Deprecated basic_string capacity [depr.string.capacity]</del></h4>
<ol>
<li><del>
 The following member is declared in addition to those members specified in 21.3.2.4:
</del></li>
<blockquote><pre>
<del>namespace std {</del>
  <del>template&lt;class charT, class traits = char_traits&lt;charT&gt;,</del>
                <del>class Allocator = allocator&lt;charT&gt;&gt;</del>
   <del>class basic_string {</del>
   <del>public:</del>
     <del>void reserve();</del>
  <del>};</del>
<del>}</del>
</pre></blockquote>

<pre><del>void reserve();</del></pre>
<li><del>
<i>Effects:</i> After this call, <tt>capacity()</tt> has an unspecified value greater
than or equal to <tt>size()</tt>. [<i>Note:</i> This is a non-binding shrink to fit
request. <i>&mdash;end note</i>]
</del></li>
</ol>
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.20">D.20 Deprecated Standard code conversion facets [depr.locale.stdcvt]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++17
</blockquote>

<p>
This feature was originally proposed for C++11 by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2007">N2007</a>
and deprecated for C++17 by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0">P0618R0</a>.
As noted at the time, the feature was underspecified and would require more work than
we wished to invest to bring it up to standard. Since then SG16 has been convened and
is producing a steady stream of work to bring reliable well-specified Unicode support
to C++.
</p>
<p>
It should also be noted that this deprecated clause pins a dated reference to a 20
year old ISO standard (revised repeatedly over the intervening decades) purely to
provide a definition of the term UCS2.
</p>
<p>
Given vendors propensity to provide ongoing support for these names under the zombie
name reservations, the strong recommendation of this paper is to remove this library
immediately from C++23, along with its binding reference to an obsolete Unicode
standard.  The weak recommendation is to do nothing at this point, until SG16 (or
some other entity) produces a clean replacement for this facility.
</p>
<p>
We note that this feature was originally added at the Kona 2007 meeting so that
(while motivated by likely user applications) the example in the then recently
added [lib.conversions] called on standard rather than user-provided classes to
illustrate use (adopted just one meeting earlier).  Therefore, if we remove
this library unilaterally, we should also revert that example back to its
original spelling.
</p>


<blockquote class="recommend">
<b>Strong recommendation:</b>
Remove this facility from the standard at the earliest opportunity.
</blockquote>

<blockquote class="draft_wording">
<h4>2 Normative references [intro.refs]</h4>
<ol>
<li>
The following documents are referred to in the text in such a way that some or
all of their content constitutes requirements of this document. For dated
references, only the edition cited applies. For undated references, the latest
edition of the referenced document (including any amendments) applies.
</li>
  <ol>
  <li>
&mdash; Ecma International, ECMAScript Language Specification, Standard Ecma-262, third edition, 1999.
  </li>
  <li>
&mdash; ISO/IEC 2382 (all parts), Information technology — Vocabulary
  </li>
  <li>
&mdash; ISO 8601:2004, Data elements and interchange formats — Information interchange — Representation of dates and times
  </li>
  <li>
&mdash; ISO/IEC 9899:2018, Programming languages — C
  </li>
  <li>
&mdash; ISO/IEC 9945:2003, Information Technology — Portable Operating System Interface (POSIX)
  </li>
  <li>
&mdash; ISO/IEC 10646, Information technology — Universal Coded Character Set (UCS)
  </li>
  <li><del>
&mdash; ISO/IEC 10646-1:1993, Information technology — Universal Multiple-Octet Coded Character Set (UCS) — Part 1: Architecture and Basic Multilingual Plane
  </del></li>
  <li>
&mdash; ISO/IEC/IEEE 60559:2011, Information technology — Microprocessor Systems — Floating-Point arithmetic
  </li>
  <li>
&mdash; ISO 80000-2:2009, Quantities and units — Part 2: Mathematical signs and symbols to be used in the natural sciences and technology
  </li>
  </ol>
<li>
The library described in Clause 7 of ISO/IEC 9899:2018 is hereinafter called
the C standard library.<sup>1</sup>
</li>
<li>
The operating system interface described in ISO/IEC 9945:2003 is hereinafter
called POSIX.
</li>
<li>
The ECMAScript Language Specification described in Standard Ecma-262 is hereinafter called ECMA-262.
</li>
<li><del>
[Note: References to ISO/IEC 10646-1:1993 are used only to support deprecated features (D.19). — end note ]
</del></li>
</ol>

<h4>16.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization:
</li>
<ol>
<li>&mdash; <tt>auto_ptr</tt>,</li>
<li>&mdash; <tt>auto_ptr_ref</tt>,</li>
<li>&mdash; <tt>binary_function</tt>,</li>
<li>&mdash; <tt>binary_negate</tt>,</li>
<li>&mdash; <tt>bind1st</tt>,</li>
<li>&mdash; <tt>bind2nd</tt>,</li>
<li>&mdash; <tt>binder1st</tt>,</li>
<li>&mdash; <tt>binder2nd</tt>,</li>
<li><ins>&mdash; <tt>codecvt_mode</tt>,</ins></li>
<li><ins>&mdash; <tt>codecvt_utf16</tt>,</ins></li>
<li><ins>&mdash; <tt>codecvt_utf8</tt>,</ins></li>
<li><ins>&mdash; <tt>codecvt_utf8_utf16</tt>,</ins></li>
<li>&mdash; <tt>const_mem_fun1_ref_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun1_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun_ref_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun_t</tt>,</li>
<li><ins>&mdash; <tt>consume_header</tt>,</ins></li>
<li><ins>&mdash; <tt>generate_header</tt>,</ins></li>
<li>&mdash; <tt>get_temporary_buffer</tt>,</li>
<li>&mdash; <tt>get_unexpected</tt>,</li>
<li>&mdash; <tt>gets</tt>,</li>
<li>&mdash; <tt>is_literal_type</tt>,</li>
<li>&mdash; <tt>is_literal_type_v</tt>,</li>
<li><ins>&mdash; <tt>little_endian</tt>,</ins></li>
<li>&mdash; <tt>mem_fun1_ref_t</tt>,</li>
<li>&mdash; <tt>mem_fun1_t</tt>,</li>
<li>&mdash; <tt>mem_fun_ref_t</tt>,</li>
<li>&mdash; <tt>mem_fun_ref</tt>,</li>
<li>&mdash; <tt>mem_fun_t</tt>,</li>
<li>&mdash; <tt>mem_fun</tt>,</li>
<li>&mdash; <tt>not1</tt>,</li>
<li>&mdash; <tt>not2</tt>,</li>
<li>&mdash; <tt>pointer_to_binary_function</tt>,</li>
<li>&mdash; <tt>pointer_to_unary_function</tt>,</li>
<li>&mdash; <tt>ptr_fun</tt>,</li>
<li>&mdash; <tt>random_shuffle</tt>,</li>
<li>&mdash; <tt>raw_storage_iterator</tt>,</li>
<li>&mdash; <tt>result_of</tt>,</li>
<li>&mdash; <tt>result_of_t</tt>,</li>
<li>&mdash; <tt>return_temporary_buffer</tt>,</li>
<li>&mdash; <tt>set_unexpected</tt>,</li>
<li>&mdash; <tt>unary_function</tt>,</li>
<li>&mdash; <tt>unary_negate</tt>,</li>
<li>&mdash; <tt>uncaught_exception</tt>,</li>
<li>&mdash; <tt>unexpected</tt>, and</li>
<li>&mdash; <tt>unexpected_handler</tt>.</li>
</ol>

<li>
The following names are reserved as member types for previous standardization,
and may not be used as a name for object-like macros in portable code:
</li>
  <ol>
<li>&mdash; <tt>argument_type</tt>,
<li>&mdash; <tt>first_argument_type</tt>,
<li>&mdash; <tt>io_state</tt>,
<li>&mdash; <tt>open_mode</tt>,
<li>&mdash; <tt>second_argument_type</tt>, and
<li>&mdash; <tt>seek_dir</tt>.
  </ol>
</li>
<li>
The name <tt>stossc</tt> is reserved as a member function for previous
standardization, and may not be used as a name for function-like macros in
portable code.
</li>
<li>
The header names
<tt>&lt;ccomplex&gt;</tt>,
<tt>&lt;ciso646&gt;</tt>,
<ins><tt>&lt;codecvt&gt;</tt>,</ins>
<tt>&lt;cstdalign&gt;</tt>,
<tt>&lt;cstdbool&gt;</tt>, and
<tt>&lt;ctgmath&gt;</tt> are reserved for previous
standardization.
</li>

</ol>

<h4><del>D.20 Deprecated Standard code conversion facets [depr.locale.stdcvt]</del></h4>
<ol>
<li><del>
The header <tt>&lt;codecvt&gt;</tt> provides code conversion facets for various
character encodings.
</del></li>
</ol>
<h4><del>D.20.1 Header <tt>&lt;codecvt&gt;</tt> synopsis [depr.codecvt.syn]</del></h4>
<pre><blockquote>
<del>namespace std {</del>
  <del>enum codecvt_mode {</del>
    <del>consume_header = 4,</del>
    <del>generate_header = 2,</del>
    <del>little_endian = 1</del>
  <del>};</del>

  <del>template&lt;class Elem, unsigned long Maxcode = 0x10ffff,</del>
    <del>codecvt_mode Mode = (codecvt_mode)0&gt;</del>
  <del>class codecvt_utf8</del>
    <del>: public codecvt&lt;Elem, char, mbstate_t&gt; {</del>
  <del>public:</del>
    <del>explicit codecvt_utf8(size_t refs = 0);</del>
    <del>~codecvt_utf8();</del>
  <del>};</del>

  <del>template&lt;class Elem, unsigned long Maxcode = 0x10ffff,</del>
    <del>codecvt_mode Mode = (codecvt_mode)0&gt;</del>
  <del>class codecvt_utf16</del>
    <del>: public codecvt&lt;Elem, char, mbstate_t&gt; {</del>
  <del>public:</del>
    <del>explicit codecvt_utf16(size_t refs = 0);</del>
    <del>~codecvt_utf16();</del>
  <del>};</del>

  <del>template&lt;class Elem, unsigned long Maxcode = 0x10ffff,</del>
    <del>codecvt_mode Mode = (codecvt_mode)0&gt;</del>
  <del>class codecvt_utf8_utf16</del>
    <del>: public codecvt&lt;Elem, char, mbstate_t&gt; {</del>
  <del>public:</del>
    <del>explicit codecvt_utf8_utf16(size_t refs = 0);</del>
    <del>~codecvt_utf8_utf16();</del>
  <del>};</del>
<del>}</del>
</blockquote></pre>

<h4><del>D.20.2 Requirements [depr.locale.stdcvt.req]</del></h4>
<ol>
<li><del>
For each of the three code conversion facets <tt>codecvt_utf8</tt>,
<tt>codecvt_utf16</tt>, and <tt>codecvt_utf8_utf16</tt>:
</del></li>
<ol>
<li><del>
&mdash; <tt>Elem</tt> is the wide-character type, such as <tt>wchar_t</tt>,
<tt>char16_t</tt>, or <tt>char32_t</tt>.
</del></li>
<li><del>
&mdash; <tt>Maxcode</tt> is the largest wide-character code that the facet will
read or write without reporting a conversion error.
</del></li>
<li><del>
&mdash; If <tt>(Mode &amp; consume_header)</tt>, the facet shall consume an
initial header sequence, if present, when reading a multibyte sequence to
determine the endianness of the subsequent multibyte sequence to be read.
</del></li>
<li><del>
&mdash; If <tt>(Mode &amp; generate_header)</tt>, the facet shall generate an
initial header sequence when writing a multibyte sequence to advertise the
endianness of the subsequent multibyte sequence to be written.
</del></li>
<li><del>
&mdash; If <tt>(Mode &amp; little_endian)</tt>, the facet shall generate a
multibyte sequence in little-endian order, as opposed to the default big-endian
order.
</del></li>
</ol>
</del></li>

<li><del>
For the facet <tt>codecvt_utf8</tt>:
<ol>
<li><del>
&mdash; The facet shall convert between UTF-8 multibyte sequences and UCS2 or
UTF-32 (depending on the size of <tt>Elem</tt>) within the program.
</del></li>
<li><del>
&mdash; Endianness shall not affect how multibyte sequences are read or written.
</del></li>
<li><del>
&mdash; The multibyte sequences may be written as either a text or a binary file.
</del></li>
</ol>
</del></li>

<li><del>
For the facet <tt>codecvt_utf16</tt>:
<ol>
<li><del>
&mdash; The facet shall convert between UTF-16 multibyte sequences and UCS2 or
UTF-32 (depending on the size of <tt>Elem</tt>) within the program.
</del></li>
<li><del>
&mdash; Multibyte sequences shall be read or written according to the
<tt>Mode</tt> flag, as set out above.
</del></li>
<li><del>
&mdash; The multibyte sequences may be written only as a binary file.
Attempting to write to a text file produces undefined behavior.
</del></li>
</ol>
</del></li>

<li><del>
For the facet <tt>codecvt_utf8_utf16</tt>:
<ol>
<li><del>
&mdash; The facet shall convert between UTF-8 multibyte sequences and UTF-16
(one or two 16-bit codes) within the program.
</del></li>
<li><del>
&mdash; Endianness shall not affect how multibyte sequences are read or written.
</del></li>
<li><del>
&mdash; The multibyte sequences may be written as either a text or a binary file.
</del></li>
</ol>
<li><del>
The encoding forms UTF-8, UTF-16, and UTF-32 are specified in ISO/IEC 10646.
The encoding form UCS-2 is specified in ISO/IEC 10646-1:1993.
</del></li>
</ol>

<h4>D.21.1 Class template wstring_convert [depr.conversions.string]</h4>
<ol>
<li>
Class template <tt>wstring_convert</tt> performs conversions between a wide
string and a byte string.  It lets you specify a code conversion facet (like
class template <tt>codecvt</tt>) to perform the conversions, without affecting
any streams or locales.  [ <i>Example:</i>  If you
<del>want to use the code conversion facet <tt>codecvt_utf8</tt></del>
<ins>have a code conversion facet called <tt>codecvt_utf8</tt> that you want to use</ins>
to output to <tt>cout</tt> a UTF-8 multibyte sequence corresponding to a wide
string, but you don’t want to alter the locale for <tt>cout</tt>, you can write
something like:
<pre><blockquote>
<ins>std::</ins>wstring_convert&lt;<del>std::</del>codecvt_utf8&lt;wchar_t&gt;&gt; myconv;
std::string mbstring = myconv.to_bytes(L"Hello\n");
std::cout &lt;&lt; mbstring;
</blockquote></pre>
&mdash; <i>end example</i> ]
</li>
</ol>

</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
take no action at this time.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>

<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.21">D.21 Deprecated convenience conversions [depr.conversions]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++17
</blockquote>

<p>
This feature was originally proposed for C++11 by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2401">N2401</a>
and deprecated for C++17 by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0">P0618R0</a>.
As noted at the time, the feature was underspecified and would require more work than
we wished to invest to bring it up to standard. Since then SG16 has been convened and
is producing a steady stream of work to bring reliable well-specified Unicode support
to C++.
</p>
<p>
Given vendors propensity to provide ongoing support for these names under the zombie
name reservations, the strong recommendation of this paper is to remove this library
immediately from the C++23 standard.  The weak recommendation is to do the minimal
work to clean up the wording to use the more precise terms that replaced <i>Requires</i>
clauses, waiting until SG16 (or some other entity) produces a clean replacement
for this facility for users to migrate to before removal.
</p>


<blockquote class="recommend">
<b>Strong recommendation:</b>
Remove this facility from the standard at the earliest opportunity.
</blockquote>

<blockquote class="draft_wording">
<h4>16.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization:
</li>
<ol>
<li>&mdash; <tt>auto_ptr</tt>,</li>
<li>&mdash; <tt>auto_ptr_ref</tt>,</li>
<li>&mdash; <tt>binary_function</tt>,</li>
<li>&mdash; <tt>binary_negate</tt>,</li>
<li>&mdash; <tt>bind1st</tt>,</li>
<li>&mdash; <tt>bind2nd</tt>,</li>
<li>&mdash; <tt>binder1st</tt>,</li>
<li>&mdash; <tt>binder2nd</tt>,</li>
<li>&mdash; <tt>const_mem_fun1_ref_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun1_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun_ref_t</tt>,</li>
<li>&mdash; <tt>const_mem_fun_t</tt>,</li>
<li>&mdash; <tt>get_temporary_buffer</tt>,</li>
<li>&mdash; <tt>get_unexpected</tt>,</li>
<li>&mdash; <tt>gets</tt>,</li>
<li>&mdash; <tt>is_literal_type</tt>,</li>
<li>&mdash; <tt>is_literal_type_v</tt>,</li>
<li>&mdash; <tt>mem_fun1_ref_t</tt>,</li>
<li>&mdash; <tt>mem_fun1_t</tt>,</li>
<li>&mdash; <tt>mem_fun_ref_t</tt>,</li>
<li>&mdash; <tt>mem_fun_ref</tt>,</li>
<li>&mdash; <tt>mem_fun_t</tt>,</li>
<li>&mdash; <tt>mem_fun</tt>,</li>
<li>&mdash; <tt>not1</tt>,</li>
<li>&mdash; <tt>not2</tt>,</li>
<li>&mdash; <tt>pointer_to_binary_function</tt>,</li>
<li>&mdash; <tt>pointer_to_unary_function</tt>,</li>
<li>&mdash; <tt>ptr_fun</tt>,</li>
<li>&mdash; <tt>random_shuffle</tt>,</li>
<li>&mdash; <tt>raw_storage_iterator</tt>,</li>
<li>&mdash; <tt>result_of</tt>,</li>
<li>&mdash; <tt>result_of_t</tt>,</li>
<li>&mdash; <tt>return_temporary_buffer</tt>,</li>
<li>&mdash; <tt>set_unexpected</tt>,</li>
<li>&mdash; <tt>unary_function</tt>,</li>
<li>&mdash; <tt>unary_negate</tt>,</li>
<li>&mdash; <tt>uncaught_exception</tt>,</li>
<li>&mdash; <tt>unexpected</tt>,<del> and</del></li>
<li>&mdash; <tt>unexpected_handler</tt><del>.</del><ins>,</ins></li>
<li><ins>&mdash; <tt>wbuffer_convert</tt>, and</ins></li>
<li><ins>&mdash; <tt>wstring_convert</tt>.</ins></li>
</ol>

<li>
The following names are reserved as member types for previous standardization,
and may not be used as a name for object-like macros in portable code:
</li>
  <ol>
<li>&mdash; <tt>argument_type</tt>,
<li>&mdash; <tt>first_argument_type</tt>,
<li>&mdash; <tt>io_state</tt>,
<li>&mdash; <tt>open_mode</tt>,
<li>&mdash; <tt>second_argument_type</tt>, and
<li>&mdash; <tt>seek_dir</tt>.
  </ol>
</li>
<li><del>
The name <tt>stossc</tt> is reserved as a member function for previous
standardization, and may not be used as a name for function-like macros in
portable code.
</del>
<ins>
The following names are reserved as member functions for previous standardization,
and may not be used as a name for function-like macros in portable code:
  <ol>
<li><ins>&mdash; <tt>converted</tt>,</ins>
<li><ins>&mdash; <tt>from_bytes</tt>,</ins>
<li><ins>&mdash; <tt>stossc</tt>, and</ins>
<li><ins>&mdash; <tt>to_bytes</tt>.</ins>
  </ol>
</ins></li>
<li>
The header names
<tt>&lt;ccomplex&gt;</tt>,
<tt>&lt;ciso646&gt;</tt>,
<tt>&lt;cstdalign&gt;</tt>,
<tt>&lt;cstdbool&gt;</tt>, and
<tt>&lt;ctgmath&gt;</tt> are reserved for previous
standardization.
</li>
</ol>

<h4><del>D.21 Deprecated convenience conversion interfaces [depr.conversions]</del></h4>
<ol>
<li><del>
The header <tt>&lt;locale&gt;</tt> (28.2) has the following additions:
</del></li>
<pre><blockquote>
<del>namespace std {</del>
  <del>template&lt;class Codecvt, class Elem = wchar_t,</del>
           <del>class WideAlloc = allocator&lt;Elem&gt;,</del>
           <del>class ByteAlloc = allocator&lt;char&gt;&gt;</del>
    <del>class wstring_convert;</del>
  <del>template&lt;class Codecvt, class Elem = wchar_t,</del>
           <del>class Tr = char_traits&lt;Elem&gt;</del>
    <del>class wbuffer_convert;</del>
<del>}</del>
</blockquote></pre>
</ol>

<h4><del>D.21.1 Class template wstring_convert [depr.conversions.string]</del></h4>
<ol>
<li><del>
Class template <tt>wstring_convert</tt> performs conversions between a wide
string and a byte string.  It lets you specify a code conversion facet (like
class template <tt>codecvt</tt>) to perform the conversions, without affecting
any streams or locales.  [ <i>Example:</i> If you want to use the code
conversion facet <tt>codecvt_utf8</tt> to output to <tt>cout</tt> a UTF-8
multibyte sequence corresponding to a wide string, but you don’t want to alter
the locale for <tt>cout</tt>, you can write something like:
<pre><blockquote>
<del>wstring_convert&lt;std::codecvt_utf8&lt;wchar_t&gt;&gt; myconv;</del>
<del>std::string mbstring = myconv.to_bytes(L"Hello\n");</del>
<del>std::cout &lt;&lt; mbstring;</del>
</blockquote></pre>
&mdash; <i>end example</i> ]
</del></del></li>

<pre><blockquote>
<del>namespace std {</del>
<del>template &lt;class Codecvt, class Elem = wchar_t,</del>
          <del>class WideAlloc = allocator&lt;Elem&gt;,</del>
          <del>class ByteAlloc = allocator&lt;char&gt;&gt;</del>
  <del>class wstring_convert {</del>
  <del>public:</del>
    <del>using byte_string = basic_string&lt;char, char_traits&lt;char&gt;, ByteAlloc&gt;;</del>
    <del>using wide_string = basic_string&lt;Elem, char_traits&lt;Elem&gt;, WideAlloc&gt;;</del>
    <del>using state_type  = typename Codecvt::state_type;</del>
    <del>using int_type    = typename wide_string::traits_type::int_type;</del>

    <del>wstring_convert() : wstring_convert(new Codecvt) {}</del>
    <del>explicit wstring_convert(Codecvt* pcvt = new Codecvt);</del>
    <del>wstring_convert(Codecvt* pcvt, state_type state);</del>
    <del>explicit wstring_convert(const byte_string&amp; byte_err,</del>
                             <del>const wide_string&amp; wide_err = wide_string());</del>
    <del>~wstring_convert();</del>

    <del>wstring_convert(const wstring_convert&amp;) = delete;</del>
    <del>wstring_convert&amp; operator=(const wstring_convert&amp;) = delete;</del>

    <del>wide_string from_bytes(char byte);</del>
    <del>wide_string from_bytes(const char* ptr);</del>
    <del>wide_string from_bytes(const byte_string&amp; str);</del>
    <del>wide_string from_bytes(const char* first, const char* last);</del>

    <del>byte_string to_bytes(Elem wchar);</del>
    <del>byte_string to_bytes(const Elem* wptr);</del>
    <del>byte_string to_bytes(const wide_string&amp; wstr);</del>
    <del>byte_string to_bytes(const Elem* first, const Elem* last);</del>

    <del>size_t converted() const noexcept;</del>
    <del>state_type state() const;</del>

  <del>private:</del>
    <del>byte_string byte_err_string;  <i>// Exposition only</i></del>
    <del>wide_string wide_err_string;  <i>// Exposition only</i></del>
    <del>Codecvt* cvtptr;              <i>// Exposition only</i></del>
    <del>state_type cvtstate;          <i>// Exposition only</i></del>
    <del>size_t cvtcount;              <i>// Exposition only</i></del>
  <del>};</del>
<del>}</del>
</blockquote></pre>

<li><del>
The class template describes an object that controls conversions between wide
string objects of class
<tt>basic_string&lt;Elem, char_traits&lt;Elem&gt;, WideAlloc&gt;</tt> and
byte string objects of class
<tt>basic_string&lt;char, char_traits&lt;char&gt;, ByteAlloc&gt;</tt>.
The class template defines the types <tt>wide_string</tt> and
<tt>byte_string</tt> as synonyms for these two types. Conversion between a
sequence of <tt>Elem</tt> values (stored in a <tt>wide_string</tt> object) and
multibyte sequences (stored in a <tt>byte_string</tt> object) is performed by
an object of class <tt>Codecvt</tt>, which meets the requirements of the
standard code-conversion facet <tt>codecvt&lt;Elem, char, mbstate_t&gt;</tt>.
</del></li>
<li><del>
An object of this class template stores:
  <ol>
  <li><del>
  &mdash; <tt>byte_err_string</tt> &mdash; a byte string to display on errors
  </del></li>
  <li><del>
  &mdash; <tt>wide_err_string</tt> &mdash; a wide string to display on errors
  </del></li>
  <li><del>
  &mdash; <tt>cvtptr</tt> &mdash; a pointer to the allocated conversion object
  (which is freed when the <tt>wstring_convert</tt> object is destroyed)
  </del></li>
  <li><del>
  &mdash; <tt>cvtstate</tt> &mdash; a conversion state object
  </del></li>
  <li><del>
  &mdash; <tt>cvtcount</tt> &mdash; a conversion count
  </del></li>
  </ol>
</del></li>

<pre><blockquote>
<del>using byte_string = basic_string&lt;char, char_traits&lt;char&gt;, ByteAlloc&gt;;</del>
</blockquote></pre>
<li><del>
The type shall be a synonym for
<tt>basic_string&lt;char, char_traits&lt;char&gt;, ByteAlloc&gt;</tt>
</del></li>

<pre><blockquote>
<del>size_t converted() const noexcept;</del>
</blockquote></pre>
<li><del>
<i>Returns:</i> <tt>cvtcount</tt>.
</del></li>

<pre><blockquote>
<del>wide_string from_bytes(char byte);</del>
<del>wide_string from_bytes(const char* ptr);</del>
<del>wide_string from_bytes(const byte_string&amp; str);</del>
<del>wide_string from_bytes(const char* first, const char* last);</del>
</blockquote></pre>
<li><del>
<i>Effects:</i> The first member function shall convert the single-element
sequence <tt>byte</tt> to a wide string. The second member function shall
convert the null-terminated sequence beginning at <tt>ptr</tt> to a wide
string. The third member function shall convert the sequence stored in str to a
wide string. The fourth member function shall convert the sequence defined by
the range <tt>[first, last)</tt> to a wide string.
</del></li>
<li><del>
In all cases:
  <ol>
  <li><del>
&mdash; If the <tt>cvtstate</tt> object was not constructed with an explicit
value, it shall be set to its default value (the initial conversion state)
before the conversion begins. Otherwise it shall be left unchanged.
  </del></li>
  <li><del>
&mdash; The number of input elements successfully converted shall be stored in
<tt>cvtcount</tt>.
  </del></li>
  </ol>
</del></li>

<li><del>
<i>Returns:</i> If no conversion error occurs, the member function shall return
the converted wide string. Otherwise, if the object was constructed with a
wide-error string, the member function shall return the wide-error string.
Otherwise, the member function throws an object of class <tt>range_error</tt>.
</del></li>

<pre><blockquote>
<del>using int_type = typename wide_string::traits_type::int_type;</del>
</blockquote></pre>
<li><del>
The type shall be a synonym for <tt>wide_string::traits_type::int_type</tt>.
</del></li>

<pre><blockquote>
<del>state_type state() const;</del>
</blockquote></pre>
<li><del>
returns <tt>cvtstate</tt>.
</del></li>

<pre><blockquote>
<del>using state_type = typename Codecvt::state_type;</del>
</blockquote></pre>
<li><del>
The type shall be a synonym for <tt>Codecvt::state_type</tt>.
</del></li>

<pre><blockquote>
<del>byte_string to_bytes(Elem wchar);</del>
<del>byte_string to_bytes(const Elem* wptr);</del>
<del>byte_string to_bytes(const wide_string&amp; wstr);</del>
<del>byte_string to_bytes(const Elem* first, const Elem* last);</del>
</blockquote></pre>
<li><del>
<i>Effects:</i> The first member function shall convert the single-element
sequence <tt>wchar</tt> to a byte string. The second member function shall
convert the null-terminated sequence beginning at <tt>wptr</tt> to a byte
string. The third member function shall convert the sequence stored in wstr to
a byte string. The fourth member function shall convert the sequence defined by
the range <tt>[first, last)</tt> to a byte string.
</del></li>

<li><del>
In all cases:
  <ol>
  <li><del>
&mdash; If the <tt>cvtstate</tt> object was not constructed with an explicit
value, it shall be set to its default value (the initial conversion state)
before the conversion begins. Otherwise it shall be left unchanged.
  </del></li>
  <li><del>
&mdash; The number of input elements successfully converted shall be stored in
<tt>cvtcount</tt>.
  </del></li>
  </ol>
</del></li>

<li><del>
<i>Returns:</i> If no conversion error occurs, the member function shall return
the converted byte string. Otherwise, if the object was constructed with a
byte-error string, the member function shall return the byte-error string.
Otherwise, the member function shall throw an object of class
<tt>range_error</tt>.
</del></li>

<pre><blockquote>
<del>using wide_string = basic_string&lt;Elem, char_traits&lt;Elem&gt;, WideAlloc&gt;;</del>
</blockquote></pre>
<li><del>
The type shall be a synonym for
<tt>basic_string&lt;Elem, char_traits&lt;Elem&gt;, WideAlloc&gt;</tt>.
</del></li>

<pre><blockquote>
<del>explicit wstring_convert(Codecvt* pcvt = new Codecvt);</del>
<del>wstring_convert(Codecvt* pcvt, state_type state);</del>
<del>explicit wstring_convert(const byte_string&amp; byte_err,</del>
    <del>const wide_string&amp; wide_err = wide_string());</del>
</blockquote></pre>
<li><del>
<i>Requires:</i> For the first and second constructors, <tt>pcvt != nullptr</tt>.
</del></li>

<li><del>
<i>Effects:</i> The first constructor shall store <tt>pcvt</tt> in
<tt>cvtptr</tt> and default values in <tt>cvtstate</tt>,
<tt>byte_err_string</tt>, and <tt>wide_err_string</tt>. The second constructor
shall store <tt>pcvt</tt> in <tt>cvtptr</tt>, <tt>state</tt> in
<tt>cvtstate</tt>, and default values in <tt>byte_err_string</tt> and
<tt>wide_err_string</tt>; moreover the stored state shall be retained between
calls to <tt>from_bytes</tt> and <tt>to_bytes</tt>. The third constructor shall
store <tt>new Codecvt</tt> in <tt>cvtptr</tt>, <tt>state_type()</tt> in
<tt>cvtstate</tt>, <tt>byte_err</tt> in <tt>byte_err_string</tt>, and
<tt>wide_err</tt> in <tt>wide_err_string</tt>.
</del></li>

<pre><blockquote>
<del>~wstring_convert();</del>
</blockquote></pre>
<li><del>
<i>Effects:</i> The destructor shall delete <tt>cvtptr</tt>.
</del></li>
</ol>


<h4><del>D.21.2 Class template wbuffer_convert [depr.conversions.buffer]</del></h4>
<ol>
<li><del>
Class template <tt>wbuffer_convert</tt> looks like a wide stream buffer, but
performs all its I/O through an underlying byte stream buffer that you specify
when you construct it. Like class template <tt>wstring_convert</tt>, it lets
you specify a code conversion facet to perform the conversions, without
affecting any streams or locales.
</del></li>
<pre><blockquote>
<del>namespace std {</del>
<del>template &lt;class Codecvt, class Elem = wchar_t, class Tr = char_traits&lt;Elem&gt;&gt;</del>
  <del>class wbuffer_convert</del>
    <del>: public basic_streambuf&lt;Elem, Tr&gt; {</del>
  <del>public:</del>
    <del>using state_type = typename Codecvt::state_type;</del>

    <del>wbuffer_convert() : wbuffer_convert(nullptr) {}</del>
    <del>explicit wbuffer_convert(streambuf* bytebuf = 0,</del>
                             <del>Codecvt* pcvt = new Codecvt,</del>
                             <del>state_type state = state_type());</del>

    <del>~wbuffer_convert();</del>

    <del>wbuffer_convert(const wbuffer_convert&amp;) = delete;</del>
    <del>wbuffer_convert&amp; operator=(const wbuffer_convert&amp;) = delete;</del>

    <del>streambuf* rdbuf() const;</del>
    <del>streambuf* rdbuf(streambuf* bytebuf);</del>

    <del>state_type state() const;</del>

  <del>private:</del>
    <del>streambuf* bufptr;        // exposition only</del>
    <del>Codecvt* cvtptr;          // exposition only</del>
    <del>state_type cvtstate;      // exposition only</del>
  <del>};</del>
<del>}</del>
</blockquote></pre>
<li><del>
The class template describes a stream buffer that controls the transmission of
elements of type <tt>Elem</tt>, whose character traits are described by the class <tt>Tr</tt>, to
and from a byte stream buffer of type <tt>streambuf</tt>.  Conversion between a sequence
of <tt>Elem</tt> values and multibyte sequences is performed by an object of class
<tt>Codecvt</tt>, which shall meet the requirements of the standard code-conversion
facet <tt>codecvt&lt;Elem, char, mbstate_t&gt;</tt>.
</del></li>

<li><del>
An object of this class template stores:
  <ol>
  <li><del>
&mdash; <tt>bufptr</tt> &mdash; a pointer to its underlying byte stream buffer
  </del></li>
  <li><del>
&mdash; <tt>cvtptr</tt> &mdash; a pointer to the allocated conversion object (which is freed when the <tt>wbuffer_convert</tt> object is destroyed)
  </del></li>
  <li><del>
&mdash; <tt>cvtstate</tt> &mdash; a conversion state object
  </del></li>
  </ol>
</del></li>

<pre><blockquote>
<del>state_type state() const;</del>
</blockquote></pre>
<li><del>
<i>Returns:</i> <tt>cvtstate</tt>.
</del></li>

<pre><blockquote>
<del>streambuf* rdbuf() const;</del>
</blockquote></pre>
</del></li>
<li><del>
<i>Returns:</i> <tt>bufptr</tt>.
</del></li>

<pre><blockquote>
<del>streambuf* rdbuf(streambuf* bytebuf);</del>
</blockquote></pre>
<li><del>
<i>Effects:</i> Stores <tt>bytebuf</tt> in <tt>bufptr</tt>.
</del></li>
<li><del>
<i>Returns:</i> The previous value of <tt>bufptr</tt>.
</del></li>

<pre><blockquote>
<del>using state_type = typename Codecvt::state_type;</del>
</blockquote></pre>
<li><del>
The type shall be a synonym for <tt>Codecvt::state_type</tt>.
</del></li>

<pre><blockquote>
<del>explicit wbuffer_convert(streambuf* bytebuf = 0,</del>
    <del>Codecvt* pcvt = new Codecvt, state_type state = state_type());</del>
</blockquote></pre>
<li><del>
<i>Requires:</i> <tt>pcvt != nullptr</tt>.
</del></li>
<li><del>
<i>Effects:</i> The constructor constructs a stream buffer object, initializes
<tt>bufptr</tt> to <tt>bytebuf</tt>, initializes <tt>cvtptr</tt> to
<tt>pcvt</tt>, and initializes <tt>cvtstate</tt> to <tt>state</tt>.
</del></li>

<pre><blockquote>
<del>~wbuffer_convert();</del>
</blockquote></pre>

<li><del>
<i>Effects:</i> The destructor shall delete <tt>cvtptr</tt>.
</del></li>
</ol>

</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Clean up wording.
</blockquote>

<blockquote class="note">
Update wording to replace <i>Requires</i> clauses (see <a href="#3.10">D.10 Requires paragraph</a>).
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.22">D.22 Deprecated locale category facets [depr.locale.category]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
This feature was added as part of the initial basic support for Unicode types
in C++11 by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2238">N2238</a>
and deprecated on the recommendation of SG16 for C++20 by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6">P0482R6</a>.
</p>

<p>
As SG16 do not report any urgent issue relating to this deprecated feature, and
are still working through the process of providing clean Unicode support in the
C++ standard library, and given the deprecation is as recent as C++20, both the
strong and weak recommendations are to take no action on this feature at this
time.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
Take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>

<blockquote class="recommend">
<b>Weak recommendation:</b>
Take no action.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>

<!---------------------- DRAFT WORDING IF WE WISH TO PROPOSE REMOVAL ------------------
<blockquote class="recommend">
<b>Weak recommendation:</b>
Remove this feature from C++23
</blockquote>

<blockquote class="draft_wording">
<h4><del>D.22 Deprecated locale category facets [depr.locale.category]</del></h4>
<ol>
<li>
<del>The <tt>ctype</tt> locale category includes the following facets as if they were specified in table Table 100 of 28.3.1.1.1.</del>
<pre>
<del>codecvt&lt;char16_t, char, mbstate_t&gt;</del>
<del>codecvt&lt;char32_t, char, mbstate_t&gt;</del>
</pre>
</li>
<li>
<del>The <tt>ctype</tt> locale category includes the following facets as if they were specified in table Table 101 of 28.3.1.1.1.</del>
<pre>
<del>codecvt_byname&lt;char16_t, char, mbstate_t&gt;</del>
<del>codecvt_byname&lt;char32_t, char, mbstate_t&gt;</del>
</pre>
</li>
<li><del>
The following class template specializations are required in addition to those
specified in 28.4.1.4. The specialization <tt>codecvt&lt;char16_t, char,
mbstate_t&gt;</tt> converts between the UTF-16 and UTF-8 encoding forms, and
the specialization <tt>codecvt&lt;char32_t, char, mbstate_t&gt;</tt> converts
between the UTF-32 and UTF-8 encoding forms.
</del></li>
</ol>
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>
<!---------------------- DRAFT WORDING IF WE WISH TO PROPOSE REMOVAL ------------------>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.23">D.23 Deprecated filesystem path factory functions [depr.fs.path.factory]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
A factory function to create path names from UTF-8 sequences was part of
the original filesystem library adopted for C++17.  However, this was the
only string-based factory function, as the preferred interface is to simply
construct a path with a string of the corresponding type/encoding.  This
factory function was deprecated in C++20 with the addition of <tt>char8_t</tt>
and the ability to now invoke a specific constructor for UTF-8 encoded
(and typed) strings.  See
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6">P0482R6</a>
for details.
</p>
<p>
The legacy API continues to function, but is more cumbersome than necessary.
There appears to be no compelling case that the API is a risk through misuse.
Therefore, given it was so recently deprecated, the strong recommendation is to
retain this feature in Annex D for C++23, giving the community time to catch
up, and consider removal again for C++26.  However, the current wording does
not follow library best practices, and should be updated to better specify the
<i>Requires</i> clauses.
</p>
<p>
However, while it does no active harm, there is always a cost to maintaining
text in the standard.  The application of zombie names means that even if we
remove this clause from Annex D in C++23, standard library vendors are likely
to continue shipping to meet customer demand for some time to come.  So the
weak recommendation is to add the names to the zombie clause, and remove
immediately from C++23.
</p>


<blockquote class="recommend">
<b>Strong recommendation:</b>
Clean up wording.
</blockquote>

<blockquote class="note">
Update wording to replace <i>Requires</i> clauses (see <a href="#3.10">D.10 Requires paragraph</a>).
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Remove this feature from C++23
</blockquote>

<blockquote class="draft_wording">
<h4>16.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization:
</li>
<ol>
<li>— <tt>auto_ptr</tt>,</li>
<li>— <tt>auto_ptr_ref</tt>,</li>
<li>— <tt>binary_function</tt>,</li>
<li>— <tt>binary_negate</tt>,</li>
<li>— <tt>bind1st</tt>,</li>
<li>— <tt>bind2nd</tt>,</li>
<li>— <tt>binder1st</tt>,</li>
<li>— <tt>binder2nd</tt>,</li>
<li>— <tt>const_mem_fun1_ref_t</tt>,</li>
<li>— <tt>const_mem_fun1_t</tt>,</li>
<li>— <tt>const_mem_fun_ref_t</tt>,</li>
<li>— <tt>const_mem_fun_t</tt>,</li>
<li>— <tt>get_temporary_buffer</tt>,</li>
<li>— <tt>get_unexpected</tt>,</li>
<li>— <tt>gets</tt>,</li>
<li>— <tt>is_literal_type</tt>,</li>
<li>— <tt>is_literal_type_v</tt>,</li>
<li>— <tt>mem_fun1_ref_t</tt>,</li>
<li>— <tt>mem_fun1_t</tt>,</li>
<li>— <tt>mem_fun_ref_t</tt>,</li>
<li>— <tt>mem_fun_ref</tt>,</li>
<li>— <tt>mem_fun_t</tt>,</li>
<li>— <tt>mem_fun</tt>,</li>
<li>— <tt>not1</tt>,</li>
<li>— <tt>not2</tt>,</li>
<li>— <tt>pointer_to_binary_function</tt>,</li>
<li>— <tt>pointer_to_unary_function</tt>,</li>
<li>— <tt>ptr_fun</tt>,</li>
<li>— <tt>random_shuffle</tt>,</li>
<li>— <tt>raw_storage_iterator</tt>,</li>
<li>— <tt>result_of</tt>,</li>
<li>— <tt>result_of_t</tt>,</li>
<li>— <tt>return_temporary_buffer</tt>,</li>
<li>— <tt>set_unexpected</tt>,</li>
<li><ins>— <tt>u8path</tt>,</ins></li>
<li>— <tt>unary_function</tt>,</li>
<li>— <tt>unary_negate</tt>,</li>
<li>— <tt>uncaught_exception</tt>,</li>
<li>— <tt>unexpected</tt>, and</li>
<li>— <tt>unexpected_handler</tt>.</li>
</ol>
</ol>

<h4><del>D.23 Deprecated filesystem path factory functions [depr.fs.path.factory]</del></h4>
<ol>
<pre>
<del>template&lt;class Source&gt;</del>
  <del>path u8path(const Source&amp; source);</del>
<del>template&lt;class InputIterator&gt;</del>
  <del>path u8path(InputIterator first, InputIterator last);</del>
</pre>
<li><del>
<i>Requires:</i> 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> or <tt>char8_t</tt>. <tt>Source</tt> meets the requirements specified in 29.11.7.3.
</del></li>
<li><del>
<i>Returns:</i></del>
<ol>
<li><del>
&mdash; If <tt>value_type</tt> is <tt>char</tt> and the current native narrow
encoding (29.11.7.2.2) is UTF-8, return <tt>path(source)</tt> or
<tt>path(first, last)</tt>; otherwise,
</del></li>
<li><del>
&mdash; if <tt>value_type</tt> is <tt>wchar_t</tt> and the native wide encoding is UTF-16,
or if <tt>value_type</tt> is <tt>char16_t</tt> or <tt>char32_t</tt>, convert
<tt>source</tt> or <tt>[first, last)</tt> to a temporary, <tt>tmp</tt>, of type
<tt>string_type</tt> and return <tt>path(tmp)</tt>; otherwise,
</del></li>
<li><del>
— convert <tt>source</tt> or <tt>[first, last)</tt> to a temporary,
<tt>tmp</tt>, of type <tt>u32string</tt> and return <tt>path(tmp)</tt>.
</del></li>
</ol>
<li><del>
<i>Remarks:</i> Argument format conversion (29.11.7.2.1) applies to the
arguments for these functions. How Unicode encoding conversions are performed
is unspecified.
</del></li>
<li><del>
[<i>Example:</i> A string is to be read from a database that is encoded in
UTF-8, and used to create a directory using the native encoding for filenames:
<blockquote><pre>
<del>namespace fs = std::filesystem;</del>
<del>std::string utf8_string = read_utf8_data();</del>
<del>fs::create_directory(fs::u8path(utf8_string));</del>
</pre></blockquote>
For POSIX-based operating systems with the native narrow encoding set to UTF-8,
no encoding or type conversion occurs.
<p><del>
For POSIX-based operating systems with the native narrow encoding not set to
UTF-8, a conversion to UTF-32 occurs, followed by a conversion to the current
native narrow encoding. Some Unicode characters may have no native character
set representation.
</del></p>
For Windows-based operating systems a conversion from UTF-8 to UTF-16 occurs.
<i>&mdash;end example</i>] <i>&mdash;end example</i>] [<i>Note:</i> The example
above is representative of a historical use of <tt>filesystem::u8path</tt>.
Passing a <tt>std::u8string</tt> to <tt>path</tt>’s constructor is preferred
for an indication of UTF-8 encoding more consistent with <tt>path</tt>’s
handling of other encodings. <i>&mdash;end note</i>]
</li>
</ol>
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>


<!-------------------------- SECTION BREAK ------------------------>


<h3><a name="3.24">D.24 Deprecated atomic operations [depr.atomics]</a></h3>

<blockquote class="note">
<b>First deprecated:</b>
C++20
</blockquote>

<p>
The original API to initialize atomic variables from C++11 was deprecated
for C++20 when the <tt>atomic</tt> template was given a default constructor to
do the right thing.  See
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0883r2">P0883R2</a>
for details.
</p>
<p>
The legacy API continues to function, but is more cumbersome than necessary.
There appears to be no compelling case that the API is a risk through misuse.
Therefore, given it was so recently deprecated, the strong recommendation is to
retain this feature in Annex D for C++23, giving the community time to catch
up, and consider removal again for C++26.
</p>
<p>
However, while it does no active harm, there is always a cost to maintaining
text in the standard.  The application of zombie names means that even if we
remove this clause from Annex D in C++23, standard library vendors are likely
to continue shipping to meet customer demand for some time to come.  So the
weak recommendation is to add the names to the zombie clause, and remove
immediately from C++23.
</p>

<p>
Additionally, the <tt>volatile</tt> qualified member functions of the
<tt>atomic</tt> class template were deprecated for C++20 by paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1831r1">P1831R1</a>.
Both the strong and weak recommendations are to leave this feature alone until
the interaction with the non-deprecated non-member functions in the
<tt>&lt;atomic&gt;</tt> header that take pointer-to-volatile-qualified type.
Possible directions would be to deprecate those non-member functions too, or to
undeprecate the volatile-qualified member functions.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
Take no action.  Reconsider for C++26.
</blockquote>

<blockquote class="note">
No change to draft.
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
Remove deprecated atomic initialization feature from C++23
</blockquote>

<blockquote class="draft_wording">
<h4>16.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization:
</li>
<ol>
<li><ins>— <tt>ATOMIC_FLAG_INIT</tt>,</ins></li>
<li><ins>— <tt>atomic_init</tt>,</ins></li>
<li><ins>— <tt>ATOMIC_VAR_INIT</tt>,</ins></li>
<li>— <tt>auto_ptr</tt>,</li>
<li>— <tt>auto_ptr_ref</tt>,</li>
<li>— <tt>binary_function</tt>,</li>
<li>— <tt>binary_negate</tt>,</li>
<li>— <tt>bind1st</tt>,</li>
<li>— <tt>bind2nd</tt>,</li>
<li>— <tt>binder1st</tt>,</li>
<li>— <tt>binder2nd</tt>,</li>
<li>— <tt>const_mem_fun1_ref_t</tt>,</li>
<li>— <tt>const_mem_fun1_t</tt>,</li>
<li>— <tt>const_mem_fun_ref_t</tt>,</li>
<li>— <tt>const_mem_fun_t</tt>,</li>
<li>— <tt>get_temporary_buffer</tt>,</li>
<li>— <tt>get_unexpected</tt>,</li>
<li>— <tt>gets</tt>,</li>
<li>— <tt>is_literal_type</tt>,</li>
<li>— <tt>is_literal_type_v</tt>,</li>
<li>— <tt>mem_fun1_ref_t</tt>,</li>
<li>— <tt>mem_fun1_t</tt>,</li>
<li>— <tt>mem_fun_ref_t</tt>,</li>
<li>— <tt>mem_fun_ref</tt>,</li>
<li>— <tt>mem_fun_t</tt>,</li>
<li>— <tt>mem_fun</tt>,</li>
<li>— <tt>not1</tt>,</li>
<li>— <tt>not2</tt>,</li>
<li>— <tt>pointer_to_binary_function</tt>,</li>
<li>— <tt>pointer_to_unary_function</tt>,</li>
<li>— <tt>ptr_fun</tt>,</li>
<li>— <tt>random_shuffle</tt>,</li>
<li>— <tt>raw_storage_iterator</tt>,</li>
<li>— <tt>result_of</tt>,</li>
<li>— <tt>result_of_t</tt>,</li>
<li>— <tt>return_temporary_buffer</tt>,</li>
<li>— <tt>set_unexpected</tt>,</li>
<li>— <tt>unary_function</tt>,</li>
<li>— <tt>unary_negate</tt>,</li>
<li>— <tt>uncaught_exception</tt>,</li>
<li>— <tt>unexpected</tt>, and</li>
<li>— <tt>unexpected_handler</tt>.</li>
</ol>
</ol>

<h4>D.24 Deprecated atomic initialization [depr.atomics]</h4>
<ol>
<li><del>
The header <tt>&lt;atomics&gt;</tt> (31.2) has the following additions.
</del></li>
<blockquote><pre>
<del>namespace std {</del>
  <del>template&lt;class T&gt;</del>
    <del>void atomic_init(volatile atomic<T>*, typename atomic&lt;T&gt;::value_type) noexcept;</del>
<del>template&lt;class T&gt;</del>
    <del>void atomic_init(atomic&lt;T&gt;*, typename atomic&lt;T&gt;::value_type) noexcept;</del>

<del>#define ATOMIC_VAR_INIT(value) <i>see below</i></del>

<del>#define ATOMIC_FLAG_INIT <i>see below</i></del>
<del>}</del>
</pre></blockquote>
</ol>

<h4>D.24.1 Volatile access [depr.atomics.volatile]</h4>
<p>
If an atomic specialization has one of the following overloads, then that
overload participates in overload resolution even if
<tt>atomic&lt;T&gt;::is_always_lock_free</tt> is <tt>false</tt>:
</p>
<blockquote><pre>
void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
T operator=(T desired) volatile noexcept;
T load(memory_order order = memory_order::seq_cst) const volatile noexcept;
operator T() const volatile noexcept;
T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept;
bool compare_exchange_weak(T&amp; expected, T desired,
                           memory_order success, memory_order failure) volatile noexcept;
bool compare_exchange_strong(T&amp; expected, T desired,
                             memory_order success, memory_order failure) volatile noexcept;
bool compare_exchange_weak(T&amp; expected, T desired,
                           memory_order order = memory_order::seq_cst) volatile noexcept;
bool compare_exchange_strong(T&amp; expected, T desired,
                             memory_order order = memory_order::seq_cst) volatile noexcept;
T fetch_<i>key</i>(T operand, memory_order order = memory_order::seq_cst) volatile noexcept;
T operator op=(T operand) volatile noexcept;
T* fetch_<i>key</i>(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept;
</pre></blockquote>


<h4><del>D.24.2 Non-member functions [depr.atomics.nonmembers]</del></h4>
<pre><del>template<&ltclass T>
  <del>void atomic_init(volatile atomic<T>* object, typename atomic&lt;T&gt;::value_type desired) noexcept;</del>
<del>template&lt;class T&gt;</del>
  <del>void atomic_init(atomic&lt;T&gt;* object, typename atomic&lt;T&gt;::value_type desired) noexcept;</del></pre>
<ol>
<li><del>
<i>Effects:</i> Equivalent to: <tt>atomic_store_explicit(object, desired, memory_order::relaxed);</tt>
</del></li>
</ol>

<h4><del>D.24.3 Operations on atomic types [depr.atomics.types.operations]</del></h4>
<pre><del>#define ATOMIC_VAR_INIT(value) <i>see below</i></del></pre>
<ol>
<li><del>
The macro expands to a token sequence suitable for constant initialization of
an atomic variable of static storage duration of a type that is
initialization-compatible with <tt>value</tt>. [<i>Note:</i> This operation may need to
initialize locks. <i>&mdash;end note</i>] Concurrent access to the variable being
initialized, even via an atomic operation, constitutes a data race. [<i>Example:</i>
<blockquote><pre>
<del>atomic&lt;int&gt; v = ATOMIC_VAR_INIT(5);</del>
</pre></blockquote>
<i>&mdash;end example</i>]
</del></li>
</ol>

<h4><del>D.24.4 Flag type and operations [depr.atomics.flag]</del></h4>
<pre><del>#define ATOMIC_FLAG_INIT see below</del></pre>
<ol>
<li><del>
<i>Remarks:</i> The macro <tt>ATOMIC_FLAG_INIT</tt> is defined in such a way
that it can be used to initialize an object of type <tt>atomic_flag</tt> to the clear
state. The macro can be used in the form:
<blockquote><pre>
<del>atomic_flag guard = ATOMIC_FLAG_INIT;</del>
</pre></blockquote>
It is unspecified whether the macro can be used in other initialization
contexts. For a complete static-duration object, that initialization shall be
static.
</del></li>
</ol>
</blockquote>

<blockquote class="note">
Draft compatibility note for Annex C.
</blockquote>


<blockquote class="review">
<b>LEWGI Review:</b>
To be determined...
</blockquote>

<!-------------------------- SECTION BREAK ------------------------>


<h2><a name="4.0">4 Other Directions</a></h2>
<p>
While practicing good housekeeping and clearing out Annex D for each
release may be the preferred option, there are other approaches that
may be taken.
</p>

<h4>Do Nothing</h4>
<p>
One approach, epitomized in the Java language, is that deprecated
features are discouraged for future use, but guaranteed to remain
available forever, and just accumulate.
</p>

<p>
This approach is rejected by this paper for a number of reasons.
First, C++ has been relatively successful in actually removing
its deprecated features in the past, a tradition we would like
to continue.  It also undercuts the available-forever rationale,
as it is not a guarantee we have given before.
</p>

<p>
A second concern is that we do not want to pay a cost to maintain
deprecated components forever - restricting growth of the language
for compatibility with deprecated features, or having to review
the whole of Annex D and upgrade components for every new language
release, in order to keep up with subtle shifts in the core
language.
</p>

<h4>Undeprecate</h4>
<p>
If something is deprecated, but later (re)discovered to have value,
then it could be revitalized and restored to the main standard.  For
example, this is exactly what happened to static function declarations
when the unnamed namespace was given internal linkage - it is merely
the classical way to say the same thing, and often clearer to write.
</p>

<p>
This may be a consideration for long-term deprecated features that
don't appear to be going anywhere, such as the <tt>strstream</tt>
facility, or the C headers.  It may be appropriate to find them a
home in the regular standard, and this is called out in the specific
reviews of each facility above.
</p>


<!-------------------------- SECTION BREAK ------------------------>


<h2><a name="5.0">5 Integrated Proposed Wording</a></h2>

<p>
This section integrates the proposed wording of the above
recommendations as the various working groups approve them
for review by the Core and Library Working Groups.  It will
apply the wording for mandating Annex D if the recommendation
is to retain a facility.
</p>

<p>
Collected summary of recommendations:
</p>
<table>
  <tr>
    <td><b>Subclause</b></td>
    <td><b>Feature</b></td>
    <td><b>Adopted Recommendation</b></td>
    <td>Action</td>
  </tr>

  <tr>
    <td>D.1</td>
    <td>Arithmetic conversion on enumerations</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.2</td>
    <td>Implicit capture of <tt>*this</tt> by reference</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.3</td>
    <td>Comma operator in subscript expressions</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.4</td>
    <td>Array comparisons</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.5</td>
    <td>Deprecated use of <tt>volatile</tt></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.6</td>
    <td>Reclare <tt>constexpr</tt> members</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.7</td>
    <td>Non-local use of TU-local entities</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.8</td>
    <td>Implicit special members</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.9</td>
    <td>C <tt>&lt;*.h&gt;</tt> headers</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.10</td>
    <td><i>Requires:</i> clauses</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.11</td>
    <td><tt>relops</tt></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.12</td>
    <td><tt>char *</tt> streams</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.13</td>
    <td>Deprecated type traits</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.14</td>
    <td>volatile <tt>tuple</tt> traits</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.15</td>
    <td>volatile <tt>variant</tt> traits</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.16</td>
    <td><tt>std::iterator</tt></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.17</td>
    <td><tt>move_iterator::operator-&gt;</tt></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.18</td>
    <td>C API to use <tt>shared_ptr</tt> atomically</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.19</td>
    <td><tt>basic_string::reserve()</tt></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.20</td>
    <td><tt>&lt;codecvt&gt;</tt></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.21</td>
    <td><tt>wstring_convert</tt> et al.</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.22</td>
    <td>Deprecated locale category facets</td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.23</td>
    <td><tt>filesystem::u8path</tt></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>D.24</td>
    <td>atomic operations</td>
    <td></td>
    <td></td>
  </tr>
 </table>

<p>
Full wording follows:
</p>

<blockquote class="note">
No change yet.  Wording will be pasted and collated from the (L)EWG recommendations when approved.
</blockquote>



<h2><a name="6.0">6 Acknowledgements</h2>
<p>
Special thanks to Hal Finkel for allowing a late update to track the latest IS
wording in the mailing.  Thanks to Stephan T. Lavavej for the early review, and
catching too many spelling and grammar errors!
</p>

<p>
Thanks to everyone who worked on flagging these facilities for deprecation,
let's take the next step!
</p>


<h2><a name="7.0">7 References</h2>
<ul>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2007">N2007</a> PROPOSED LIBRARY ADDITIONS FOR CODE CONVERSION, P.J. Plauger</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2238">N2238</a> Minimal Unicode support for the standard library, Matthew Austern</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2401">N2401</a> Code Conversion Facets for the Standard C++ Library, P.J. Plauger</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3201">N3201</a> Moving right along, Bjarne Stroustrup</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3203">N3203</a> Tightening the conditions for generating implicit moves, Jens Maurer</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4086">N4086</a> Removing trigraphs??!, Richard Smith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0174r0">P0174R2</a> Deprecating Vestigial Library Parts in C++17, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0386r2">P0386R2</a> Inline Variables, Hal Finkel and Richard Smith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6">P0482R6</a> char8_t: A type for UTF-8 characters and strings, Tom Honermann</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0">P0618R0</a> Deprecating <tt>&lt;codecvt&gt;</tt>, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0619r4">P0619R4</a> Reviewing Deprecated Facilities of C++17 for C++20, Alisdair Meredith, Stephan T. Lavavej, Tomasz Kamiński</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0718r2">P0718R2</a> Revising <tt>atomic_shared_ptr</tt> for C++20, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0767r1">P0767R1</a> Deprecate POD, Jens Maurer</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0768r1">P0768R1</a> Library Support for the Spaceship (Comparison) Operator, Walter E. Brown</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0788r3">pP788R3</a> Standard Library Specification in a Concepts and Contracts World, Walter E. Brown</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0806r2">P0806R2</a> Deprecate implicit capture of <tt>this</tt> via <tt>[=]</tt>, Thomas Köppe</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0883r2">P0883R2</a> Fixing Atomic Initialization, Nicolai Josuttis</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0966r1">P0966R1</a> <tt>string::reserve</tt> Should Not Shrink, Mark Zeren, Andrew Luo</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1152r4">P1152R4</a> Deprecating <tt>volatile</tt>, JF Bastien</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1161r3">P1161R3</a> Deprecate uses of the comma operator in subscripting expressions, Corentin Jabot</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1120r0">P1120R0</a> Consistency improvements for &lt;=&gt; and other comparison operators, Richard Smith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1252r2">P1252R2</a> Ranges Design Cleanup, Casey Carter</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1815r2">P1815R2</a> Translation-unit-local entities, S. Davis Herring</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1831r1">P1831R1</a> Deprecating <tt>volatile</tt>: library, JF Bastien</li>
</ul>

</body>
</html>
