<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++17 for C++20</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;
    }
  </style>
</head>

<body>
<table>
<tr>
  <td align="left">Doc. no.</td>
  <td align="left">P0619R0</td>
</tr>
<tr>
  <td align="left">Date:</td>
  <td align="left">2017-03-17</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</td>
</tr><tr>
  <td align="left"></td>
  <td align="left">Library Evolution Working Group</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>
<tr>
  <td/>
  <td align="left">Stephan T. Lavavej &lt;<a href="mailto:stl@microsoft.com">stl@microsoft.com</a>&gt;</td>
</tr>
<tr>
  <td/>
   <td align="left">Tomasz Kamiński &lt;tomaszkam at gmail dot com&gt;</td>
</tr>
</table>

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

<h2>Table of Contents</h2>
<ol start="0">
<li><a href="#rev.hist">Revision History</a></li>
  <ul>
  <li><a href="#rev.0">Revision 0</a></li>
  </ul>
<li><a href="#1.0">Introduction</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 Redeclaration of static constexpr data members [depr.static_constexpr]</a></li>
  <li><a href="#3.2">D.2 Implicit declaration of copy functions [depr.impldec]</a></li>
  <li><a href="#3.3">D.3 Deprecated exception specifications [depr.except.spec]</a></li>
  <li><a href="#3.4">D.4 C++ standard library headers [depr.cpp.headers]</a></li>
  <li><a href="#3.5">D.5 C standard library headers [depr.c.headers]</a></li>
  <li><a href="#3.6">D.6 char* streams [depr.str.strstreams]</a></li>
  <li><a href="#3.7">D.7 uncaught_exception [depr.uncaught]</a></li>
  <li><a href="#3.8">D.8 Old adaptable function bindings [depr.func.adaptor.binding]</a></li>
  <li><a href="#3.9">D.9 The default allocator [depr.default.allocator]</a></li>
  <li><a href="#3.10">D.10 Raw storage iterator [depr.storage.iterator]</a></li>
  <li><a href="#3.11">D.11 Temporary buffers [depr.temporary.buffer]</a></li>
  <li><a href="#3.12">D.12 Deprecated type traits [depr.meta.types]</a></li>
  <li><a href="#3.13">D.13 Deprecated iterator primitives [depr.iterator.primitives]</a></li>
  <li><a href="#3.14">D.14 Deprecated shared_ptr observers [depr.util.smartptr.shared.obs]</a></li>
  <li><a href="#3.15">D.15 Standard code conversion facets [depr.locale.stdcvt]</a></li>
  <li><a href="#3.16">D.16 Deprecated Character Conversions [depr.conversions]</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 2017 post-Kona mailing.
</p>


<h2><a name="1.0">1 Introduction</a></h2>
<p>
This paper evaluates all the existing deprecated facilities in
the C++17 standard, and recommends a subset as candidates for removal
in C++20.
</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.
</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.  In practice,
C++ has some long-term deprecated facilities that are difficult to
remove, and equally difficult to rehabilitate.  Also, with the three
year release cadence for the C++ standard, we will often be considering
removal of features whose deprecated status has barely reached print.
</p>
<p>
The benefits of making the choice to remove early 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>
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 C++14.  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>20.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>
<p>
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>


<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++17 DIS, including
the revised clause numbers.  However, it will be updated to properly
reflect the final document in the pre-Toronto mailing, incorporating
any feedback we accrue in the meantime.
</p>

<h3><a name="3.1">D.1 Redeclaration of static constexpr data members [depr.static_constexpr]</a></h3>
<p>
Redundant <tt>constexpr</tt> declarations are a relatively recent feature
of modern C++, as the <tt>constexpr</tt> facility was not introduced until
C++11.  That said, the redundant redeclaration was not deprecated until
C++17, so there has not yet been much time for user code to respond to the
deprecation notice.
</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++20.  That
said, there is also an argument to be made for cleanliness in the standard
and prompt removal of deprecated features.  If we do wish to consider the
removal of redundant <tt>constexpr</tt> declarations, it would be best to
do so early, so that there is an opportunity for early adopters to shout
if the feature is relied on more heavily than expected.
</p>

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

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


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

<blockquote>
<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 (10.1.1) or a <i>linkage-specification</i><sup>26</sup> (10.5) 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 (12.2, 12.2.3),</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.1),</del></li>
<li>&mdash; it is a class name declaration (12.1),</li>
<li>&mdash; it is an <i>opaque-enum-declaration</i> (10.2),</li>
<li>&mdash; it is a <i>template-parameter</i> (17.1),</li>
<li>&mdash; it is a <i>parameter-declaration</i> (11.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 (10.1.3),</li>
<li>&mdash; it is an <i>alias-declaration</i> (10.1.3),</li>
<li>&mdash; it is a <i>using-declaration</i> (10.3.3),</li>
<li>&mdash; it is a <i>deduction-guide</i> (17.9),</li>
<li>&mdash; it is a <i>static_assert-declaration</i> (Clause 10),</li>
<li>&mdash; it is an <i>attribute-declaration</i> (Clause 10),</li>
<li>&mdash; it is an <i>empty-declaration</i> (Clause 10),</li>
<li>&mdash; it is a <i>using-directive</i> (10.3.4),</li>
<li>&mdash; it is an explicit instantiation declaration (17.7.2), or</li>
<li>&mdash; it is an explicit specialization (17.7.3) whose <i>declaration</i> is not a definition.</li>
  </ol>
</li>
</ol>

<h4>12.2.3.2 Static data members [class.static.data]</h4>
<ol start="3">
<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 (8.20). The member shall still
be defined in a namespace scope if it is odr-used (6.2) 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.1).</del> Declarations of other static data members shall
not specify a <i>brace-or-equal-initializer</i>.
</li>
</ol>

<h4><del>D.1 Redeclaration of static constexpr data members [depr.static_constexpr]</del></h4>
<ol>
<li><del>
For compatibility with prior C++ International Standards, a constexpr 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 class="note">
Draft compatibility note for Annex C.
</blockquote>

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


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


<h3><a name="3.2">D.2 Implicit declaration of copy functions [depr.impldec]</a></h3>
<p>
This feature was deprecated towards the end of the C++11 development cycle,
and was heavily relied on prior to that.  That said, many of the deprecated
features are implicitly deleted if any move operations are declared, and
modern users are increasingly familiar with this idiom, and may find the older
deprecated behavior jarring.  It is expected that compilers will give good
warnings for code that breaks with the removal of this feature, much as they
advise about its impending demise with deprecation warnings today.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
take decisive action early in the C++20 development cycle, so early adopters
can shake out the reamaining 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++20.
</blockquote>

<blockquote>
<blockquote class="note">
Consider 11.4.2 [dcl.fct.def.default]p5, explicitly defaulting a copy ctor
after a user-declaration in the class definition.  If this definition were
to become deleted, the program would become ill-formed, and that would be
bad.  Ensure we have wording to cover this case.
</blockquote>

<h4>15.8.1 Copy/move constructors [class.copy.ctor]</h4>
<ol start="6">
<li>
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<ins>,</ins><del> or</del> move assignment
operator,<ins> copy assignment operator, or destructor,</ins> the implicitly
declared copy constructor is defined as deleted; otherwise, it is defined as
defaulted (11.4). <del>The latter case is deprecated if the class has a
user-declared copy assignment operator or a user-declared destructor.</del>
</li>
</ol>

<h4>15.8.2 Copy/move assignment operator [class.copy.assign]</h4>
<ol start="2">
<li>
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<ins>,</ins> <del>or</del> move assignment operator, <ins>copy
constructor, or destructor,</ins> the implicitly declared copy assignment
operator is defined as deleted; otherwise, it is defined as defaulted (11.4).
<del>The latter case is deprecated if the class has a user-declared copy
constructor or a user-declared destructor.</del> The implicitly-declared copy
assignment operator for a class <tt>X</tt> will have the form...
</li>
</ol>

<h4><del>D.2 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 class="note">
Audit standard for examples like 10.1.7.2 [dcl.type.simple]p5 that rely on
implicit copies that will now be deleted.
</blockquote>

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

</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.
</blockquote>


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


<h3><a name="3.3">D.3 Deprecated exception specifications [depr.except.spec]</a></h3>
<p>
The deprecated exception specification <tt>throw()</tt> was retained in C++17,
when other exception specifications were removed, to retain compatibility for
the only form that saw widespread use.  Its impact on the remaining standard
is minimal, so it costs little to retain it for another iteration, giving users
a reasonable amout of time to complete their transition, and retaining a viable
conversion path from C++03 directly to C++20.  It is worth noting that the
feature will have been deprecated for most of a decade when C++20 is published
though.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
take no action now, and plan to remove this feature in C++23.
</blockquote>

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


<blockquote class="recommend">
<b>Weak recommendation:</b>
remove the final traces of the deprecated exception specification syntax:
</blockquote>

<blockquote>
<h4>18.4 Exception specifications [except.spec]</h4>
<ol>
<li>
The predicate indicating whether a function cannot exit via an exception is
called the <i>exception specification</i> of the function. If the predicate is false,
the function has a <i>potentially-throwing exception specification</i>, otherwise it
has a <i>non-throwing exception specification</i>. The exception specification is
either defined implicitly, or defined explicitly by using a <i>noexcept-specifier</i>
as a suffix of a function declarator (11.3.5).

<blockquote><pre>
<i>noexcept-specifier</i> :
  <tt>noexcept</tt> ( <i>constant-expression</i> )</tt>
  <tt>noexcept</tt>
  <del><tt>throw</tt> ( )</del>
</pre></blockquote>
</li>
<li>
In a <i>noexcept-specifier</i>, the <i>constant-expression</i>, if supplied,
shall be a contextually converted constant expression of type <tt>bool</tt>
(8.20); that constant expression is the exception specification of the function
type in which the <i>noexcept-specifier</i> appears. A ( token that follows
<tt>noexcept</tt> is part of the <i>noexcept-specifier</i> and does not
commence an initializer (11.6). The <i>noexcept-specifier</i> <tt>noexcept</tt>
without a <i>constant-expression</i> is equivalent to the <i>noexcept-specifier</i>
<tt>noexcept(true)</tt>. <del>The <i>noexcept-specifier</i> <tt>throw()</tt> is
deprecated (D.3), and equivalent to the <i>noexcept-specifier</i>
<tt>noexcept(true)</tt>.</del>
</li>
</ol>

<ol start="11">
<li>[ <i>Example:</i>
<pre>
   struct A {
     A(int = (A(5), 0)) noexcept;
     A(const A&amp;) noexcept;
     A(A&amp;&amp;) noexcept;
     ~A();
   };
   struct B {
     B() <del>throw()</del><ins>noexcept</ins>;
     B(const B&amp;) = default;  <i>// implicit exception specification is <tt>noexcept(true)</tt></i>
     B(B&amp;&amp;, int = (throw Y(), 0)) noexcept;
     ~B() noexcept(false);
   };
   int n = 7;
   struct D : public A, public B {
     int * p = new int[n];
     <i>// D::D() potentially-throwing, as the new operator may throw <tt>bad_alloc</tt> or <tt>bad_array_new_length</tt></i>
     <i>// D::D(const D&amp;) non-throwing</i>
     <i>// D::D(D&amp;&amp;) potentially-throwing, as the default argument for B's constructor may throw</i>
     <i>// D::~D() potentially-throwing</i>
   };
</pre>
Furthermore, if <tt>A::~A()</tt> were virtual, the program would be ill-formed
since a function that overrides a virtual function from a base class shall not
have a potentially-throwing exception specification if the base class function
has a non-throwing exception specification. &mdash; <i>end example</i> ]
</li>
</ol>

<h4><del>D.3 Deprecated exception specifications [depr.except.spec]</del></h4>
<ol>
<li><del>The <i>noexcept-specifier</i> <tt>throw()</tt> is deprecated.</del></li>
</ol>

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


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


<h3><a name="3.4">D.4 C++ standard library headers [depr.cpp.headers]</a></h3>
<p>
The deprecated compatibility headers for C++ are mostly vacuous,
merely redirecting to other headers, or defining macros that are
alreadty reserved to the implementation.  By aliasing the C headers
providing macros to emulate the language support for keywords in C++,
there is no real value intended by supplying a C++ form of these
headers.  There should be minimal harm in removing these headers,
and it would remove a possible risk of confusion, with users trying
to understand if this is some clever compatibility story for mixed
C/C++ projects.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
remove the final traces of the deprecated compatibility headers:
</blockquote>

<blockquote>
<h4>20.5.1.2 Headers [headers]</h4>
<p>
Table 17 &mdash; C++ headers for C library facilities
</p>
<table>
  <tr>
    <td><tt>&lt;cassert&gt;</tt></td>
    <td><tt>&lt;cinttypes&gt;</tt></td>
    <td><tt>&lt;csignal&gt;</tt></td>
    <td><tt>&lt;cstdio&gt;</tt></td>
    <td><tt>&lt;cwchar&gt;</tt></td>
  </tr>
  <tr>
    <td><tt><del>&lt;ccomplex&gt;</del></tt></td>
    <td><tt><del>&lt;ciso646&gt;</del></tt></td>
    <td><tt><del>&lt;cstdalign&gt;</del></tt></td>
    <td><tt>&lt;cstdlib&gt;</tt></td>
    <td><tt>&lt;cwctype&gt;</tt></td>
  </tr>
  <tr>
    <td><tt>&lt;cctype&gt;</tt></td>
    <td><tt>&lt;climits&gt;</tt></td>
    <td><tt>&lt;cstdarg&gt;</tt></td>
    <td><tt>&lt;cstring&gt;</tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt>&lt;cerrno&gt;</tt></td>
    <td><tt>&lt;clocale&gt;</tt></td>
    <td><tt><del>&lt;cstdbool&gt;</del></tt></td>
    <td><tt><del>&lt;ctgmath&gt;</del></tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt>&lt;cfenv&gt;</tt></td>
    <td><tt>&lt;cmath&gt;</tt></td>
    <td><tt>&lt;cstddef&gt;</tt></td>
    <td><tt>&lt;ctime&gt;</tt></td>
    <td><tt></tt></td>
  </tr>
  <tr>
    <td><tt>&lt;cfloat&gt;</tt></td>
    <td><tt>&lt;csetjmp&gt;</tt></td>
    <td><tt>&lt;cstdint&gt;</tt></td>
    <td><tt>&lt;cuchar&gt;</tt></td>
    <td><tt></tt></td>
  </tr>
</table>

<h4>20.5.1.3 Freestanding implementations [compliance]</h4>
<p>
Table 19 &mdash; C++ headers for freestanding implementations
</p>
<table>
  <tr>
    <td></td>
    <td><b>subclause</b></td>
    <td><b>header</b></td>
  </tr>
  <tr>
    <td></td>
    <td></td>
    <td><tt><del>&lt;ciso646&gt;</del></tt></td>
  </tr>
  <tr>
    <td>21.2</td>
    <td>Types</td>
    <td><tt>&lt;cstddef&gt;</tt></td>
  </tr>
  <tr>
    <td>21.3</td>
    <td>Implementation properties</td>
    <td><tt>&lt;cfloat&gt;</tt> <tt>&lt;limits&gt;</tt> <tt>&lt;climits&gt;</tt></td>
  </tr>
  <tr>
    <td>21.4</td>
    <td>Integer types</td>
    <td><tt>&lt;cstdint&gt;</tt></td>
  </tr>
  <tr>
    <td>21.5</td>
    <td>Start and termination</td>
    <td><tt>&lt;cstdlib&gt;</tt></td>
  </tr>
  <tr>
    <td>21.6</td>
    <td>Dynamic memory management</td>
    <td><tt>&lt;new&gt;</tt></td>
  </tr>
  <tr>
    <td>21.7</td>
    <td>Type identification</td>
    <td><tt>&lt;typeinfo&gt;</tt></td>
  </tr>
  <tr>
    <td>21.8</td>
    <td>Exception handling</td>
    <td><tt>&lt;exception&gt;</tt></td>
  </tr>
  <tr>
    <td>21.9</td>
    <td>Initializer lists</td>
    <td><tt>&lt;initializer_list&gt;</tt></td>
  </tr>
  <tr>
    <td>21.10</td>
    <td>Other runtime support</td>
    <td><tt>&lt;cstdarg&gt;</tt> </td>
  </tr>
  <tr>
    <td>23.15</td>
    <td>Type traits</td>
    <td><tt>&lt;type_traits&gt;</tt></td>
  </tr>
  <tr>
    <td>32</td>
    <td>Atomics</td>
    <td><tt>&lt;atomic&gt;</tt></td>
  </tr>
  <tr>
    <td><del>D.4.2, D.4.3</del></td>
    <td><del>Deprecated headers</del></td>
    <td><del><tt>&lt;cstdalign&gt;</tt> <tt>&lt;cstdbool&gt;</tt></del></td>
  </tr>
</table>

<h4>20.5.4.3.1 Zombie names [zombie.names]</h4>
<ol start="2">
<li><ins>
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.
</ins></li>
</ol>

<h4>C.5.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 D.4, but their use is deprecated in C++.
</li>
<li>
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++.
</li>
<li>
The <del>headers <tt>&lt;ccomplex&gt;</tt> (29.5.11) and <tt>&lt;ctgmath&gt;</tt>
(29.9.6), as well as their corresponding</del> C headers <tt>&lt;complex.h&gt;</tt>
and <tt>&lt;tgmath.h&gt;</tt><del>,</del> do not contain any of the content from the C
standard library and instead merely include other headers from the C++ standard library.
</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>

<h4>C.5.2.4 Header <tt>&lt;iso646.h&gt;</tt> [diff.header.iso646.h]</h4>
<ol>
<li>
The tokens <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).
<del>They do not appear as macro names defined in <tt>&lt;ciso646&gt;</tt>.</del>
</li>
</ol>

<h4>C.5.2.5 Header <tt>&lt;stdalign.h&gt;</tt> [diff.header.stdalign.h]</h4>
<ol>
<li>
The token <tt>alignas</tt> is a keyword in this International Standard (5.11).
<del>It does not appear as a macro name defined in <tt>&lt;cstdalign&gt;</tt> (21.10.4).</del>
</li>
</ol>

<h4>C.5.2.6 Header <tt>&lt;stdbool.h&gt;</tt> [diff.header.stdbool.h]</h4>
<ol>
<li>
The tokens <tt>bool</tt>, <tt>true</tt>, and <tt>false</tt> are keywords in this International Standard (5.11).
<del>They do not appear as macro names defined in <tt>&lt;cstdbool&gt;</tt> (21.10.3).</del>
</li>
</ol>

<h4><del>D.4 C++ standard library headers [depr.cpp.headers]</del></h4>
<ol>
<li><del>
For compatibility with prior C++ International Standards, the C++ standard
library provides headers &lt;ccomplex&gt; (D.4.1), &lt;cstdalign&gt; (D.4.2), &lt;cstdbool&gt;
(D.4.3), and &lt;ctgmath&gt; (D.4.4). The use of these headers is deprecated.
</del></li>
</ol>

<h4><del>D.4.1 Header &lt;ccomplex&gt; synopsis [depr.ccomplex.syn]</del></h4>
<blockquote><pre>
<del>#include &lt;complex&gt;</del>
</pre></blockquote>
<ol>
<li><del>
The header &lt;ccomplex&gt; behaves as if it simply includes the header &lt;complex&gt; (29.5.1).
</del></li>
</ol>

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

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

<h4><del>D.4.4 Header &lt;ctgmath&gt; synopsis [depr.ctgmath.syn]</del></h4>
<blockquote><pre>
<del>#include &lt;complex&gt;</del>
<del>#include &lt;cmath&gt;</del>
</pre></blockquote>
<ol>
<li><del>
The header &lt;ctgmath&gt; simply includes the headers &lt;complex&gt; (29.5.1) and &lt;cmath&gt; (29.9.1).
</del></li>
<li><del>
[ <i>Note:</i> The overloads provided in C by type-generic macros are already
provided in &lt;complex&gt; and &lt;cmath&gt; by &quot;sufficient&quot; additional overloads. &mdash; end note ]
</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 C++23.
</blockquote>

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

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



<h3><a name="3.5">D.5 C standard library headers [depr.c.headers]</a></h3>
<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++ langauge.
</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.  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 may be worth undeprecating the headers, and
finding 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.  Therefore, we make no
recommendation to undeprecate these headers for C++20, but
will keep looking into this space for C++23.
</p>


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

<blockquote>
<h4>20.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.2).
</li>
<li><del>
The C standard library headers (D.4) shall include only their corresponding C++
standard library header, as described in 20.5.1.2.  </li>
</del></ol>

<blockquote class="note">
Actually, probably want to merge this into <b>20.5.1.2 Headers [headers]</b>.
Also, fix up cross-references to list stable labels.
</blockquote>
<h5><ins>20.5.5.2.1 C standard library headers [c.headers]</ins></h5>
<ol>
<li><ins>
For compatibility with the C standard library, the C++ standard library
provides the C headers shown in Table 141.
</ins></li>
<p><ins>
Table 141 &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>

<li><ins>
The header <tt>&lt;complex.h</tt>&gt; behaves as if it simply includes the
header <tt>&lt;complex</tt>&gt;.  The header <tt>&lt;tgmath.h&gt;</tt> behaves
as if it simply includes the headers <tt>&lt;complex&gt;</tt> and
<tt>&lt;cmath&gt;</tt>.
</ins></li>
<li><ins>
Every other C header, each of which has a name of the form <tt>name.h</tt>,
behaves as if each name placed in the standard library namespace by the
corresponding cname header is placed within the global namespace scope, except
for the functions described in 29.9.5, the declaration of std::byte (21.2.1),
and the functions and function templates described in 21.2.5. It is unspecified
whether these names are first declared or defined within namespace scope
(6.3.6) of the namespace std and are then injected into the global namespace
scope by explicit using-declarations (10.3.3).
</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>. &mdash; <i>end
example</i> ]
</ins></li>
</ol>
</ol>

<h4><del>D.5 C standard library headers [depr.c.headers]</del></h4>
<ol>
<li><del>
1 For compatibility with the C standard library, the C++ standard library
provides the <i>C headers shown</i> in Table 141.
</del></li>
<p><del>
Table 141 &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>

<li><del>
The header <tt>&lt;complex.h</tt>&gt; behaves as if it simply includes the
header <tt>&lt;ccomplex</tt>&gt;  The header <tt>&lt;tgmath.h&gt;</tt> behaves
as if it simply includes the header <tt>&lt;ctgmath&gt;</tt>.
</del></li>
<li><del>
Every other C header, each of which has a name of the form <tt>name.h</tt>,
behaves as if each name placed in the standard library namespace by the
corresponding <tt><i>cname</i></tt> header is placed within the global
namespace scope, except for the functions described in 29.9.5, the declaration
of std::byte (21.2.1), and the functions and function templates described in
21.2.5. It is unspecified whether these names are first declared or defined
within namespace scope (6.3.6) of the namespace std and are then injected into
the global namespace scope by explicit using-declarations (10.3.3).
</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>. &mdash; <i>end
example</i> ]
</del></li>
</ol>
</blockquote>


<blockquote class="recommend">
<b>Weak recommendation:</b>
In addition to tbe above, also remove the corresponding C headers from the
C++ standard, much as we have no corresponding <tt>&lt;stdatomic.h&gt;</tt>,
<tt>&lt;stdnoreturn.h&gt;</tt>, or <tt>&lt;threads.h&gt;</tt>, headers.
</blockquote>

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

<blockquote>
<h5><ins>20.5.5.2.1 C standard library headers [c.headers]</ins></h5>
<ol>
<li><ins>
For compatibility with the C standard library, the C++ standard library
provides the C headers shown in Table 141.
</ins></li>
<p><ins>
Table 141 &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><del>
The header <tt>&lt;complex.h</tt>&gt; behaves as if it simply includes the
header <tt>&lt;complex</tt>&gt;.  The header <tt>&lt;tgmath.h&gt;</tt> behaves
as if it simply includes the headers <tt>&lt;complex&gt;</tt> and
<tt>&lt;cmath&gt;</tt>.
</del></li>
</blockquote>

<h4>C.5.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 D.5, but their use is deprecated in C++.
</li>
<li>
There are no C++ headers for the C headers <ins><tt>&lt;complex.h&gt;</tt>,</ins>
&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 class="note">
Draft compatibility note for Annex C.
</blockquote>


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


<h3><a name="3.6">D.6 <tt>char*</tt> streams [depr.str.strstreams]</a></h3>
<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 do at this point.
</p>
<blockquote class="recommend">
<b>Strong recommendation:</b>
take no action.
</blockquote>

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


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

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


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


<h3><a name="3.7">D.7 <tt>uncaught_exception</tt> [depr.uncaught]</a></h3>
<p>
This function is a remnant of the early attempts to implement an
exception-aware API.  It turned out to be surprisingly hard to specify,
not least because it was not entirely obvious at the time that more than
one exception may be simultaneously active in a single thread.
</p>

<p>
The function seems harmless, and takes up little space in the standard,
so there is no immediate rush to remove it.  As a low level (language support)
part of the free-standing library, it is likely that some ABIs depend on
its continued existence, although library vendors would remain free to
continue supplying it for their ABI needs under the zombie names policy.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
take no action yet, unless this is our once-in-a-decade opportunity to
break ABIs.
</blockquote>

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


<blockquote class="recommend">
<b>Weak recommendation:</b>
remove the function, and add a new entry to the [zombie.names] clause.
</blockquote>

<blockquote>
<h4>20.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization: <tt>auto_ptr</tt>, <tt>binary_function</tt>, <tt>bind1st</tt>,
<tt>bind2nd</tt>, <tt>binder1st</tt>, <tt>binder2nd</tt>,
<tt>const_mem_fun1_ref_t</tt>, <tt>const_mem_fun1_t</tt>,
<tt>const_mem_fun_ref_t</tt>, <tt>const_mem_fun_t</tt>,
<tt>get_unexpected</tt>, <tt>mem_fun1_ref_t</tt>, <tt>mem_fun1_t</tt>,
<tt>mem_fun_ref_t</tt>, <tt>mem_fun_ref</tt>, <tt>mem_fun_t</tt>,
<tt>mem_fun</tt>, <tt>pointer_to_binary_function</tt>,
<tt>pointer_to_unary_function</tt>, <tt>ptr_fun</tt>, <tt>random_shuffle</tt>,
<tt>set_unexpected</tt>, <tt>unary_function</tt>, <ins><tt>uncaught_exception</tt>,</ins>
<tt>unexpected</tt>, and <tt>unexpected_handler</tt>.
</li>
</ol>

<h4><del>D.7 uncaught_exception [depr.uncaught]</del></h4>
<ol>
<li><del>
The header <tt>&lt;exception&gt;</tt> has the following addition:
</del></li>
<pre><blockquote>
<del>namespace std {</del>
  <del>bool uncaught_exception() noexcept;</del>
<del>}</del>
</blockquote></pre>
<pre><del>bool uncaught_exception() noexcept;</del></pre>
<li><del>
<i>Returns:</i> <tt>uncaught_exceptions() &gt; 0</tt>.
</del></li>
</ol>
</blockquote>

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


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


<h3><a name="3.8">D.8 Old adaptable function bindings [depr.func.adaptor.binding]</a></h3>
<p>
The adaptable function bindings were a strong candidate for removal in C++17,
but were retained only because there was no adequate replacement for users of
the unary/binary negators to migrate to.  That feature, <tt>std::not_fn</tt>,
was added to C++17 to allow the migration path, with the plan to remove this
obsolete facility at the first opportunity in the C++20 cycle.
</p>

<p>
There are several superior alternatives available to the classic adaptable
function APIs.  <tt>std::bind</tt> does not rely on mark-up with specific
aliases in classes, and extends to an arbitrary number of parameters.
Lambda expressions are often simpler to read, and integrated directly
into the language.
</p>

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

<blockquote>
<h4>20.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization: <tt>auto_ptr</tt>, <tt>binary_function</tt>,
<ins><tt>binary_negate</tt>,</ins> <tt>bind1st</tt>, <tt>bind2nd</tt>,
<tt>binder1st</tt>, <tt>binder2nd</tt>, <tt>const_mem_fun1_ref_t</tt>,
<tt>const_mem_fun1_t</tt>, <tt>const_mem_fun_ref_t</tt>,
<tt>const_mem_fun_t</tt>, <tt>get_unexpected</tt>, <tt>mem_fun1_ref_t</tt>,
<tt>mem_fun1_t</tt>, <tt>mem_fun_ref_t</tt>, <tt>mem_fun_ref</tt>,
<tt>mem_fun_t</tt>, <tt>mem_fun</tt>, <ins><tt>not1</tt>, <tt>not2</tt>,</ins>
<tt>pointer_to_binary_function</tt>, <tt>pointer_to_unary_function</tt>,
<tt>ptr_fun</tt>, <tt>random_shuffle</tt>, <tt>set_unexpected</tt>,
<tt>unary_function</tt>, <ins><tt>unary_negate</tt>,</ins> <tt>unexpected</tt>,
and <tt>unexpected_handler</tt>.
</li>
<li><ins>
The following names are reserved as member types for previous standardization,
and may not be used as names for object-like macros in portable code:
<tt>argument_type</tt>, <tt><tt>first_argument_type</tt></tt>, and
<tt>second_argument_type</tt>.
</ins></li>
</ol>

<blockquote class="note">
Note that <tt>result_type</tt> is deliberately omitted from this list
as it still has a variety of non-deprecated uses within the standard library.
</blockquote>


<h4><del>D.8 Old Adaptable Function Bindings  [depr.func.adaptor.binding]</del></h3>

<h4><del>D.8.1 Weak Result Types [depr.weak.result_type]</del></h4>
<ol>
  <li><del>A call wrapper (23.14.2) may have a <i>weak result type</i>.  If it does, the type
      of its member type <tt>result_type</tt> is based on the type <tt>T</tt> of the wrapper's
      target object:
  </del></li>
  <ol>
    <li><del>if <tt>T</tt> is a pointer to function type, <tt>result_type</tt> shall be a
        synonym for the return type of <tt>T</tt>;</del></li>
    <li><del>if <tt>T</tt> is a pointer to member function, <tt>result_type</tt> shall be a
        synonym for the return type of <tt>T</tt>;</del></li>
    <li><del>if <tt>T</tt> is a class type and the qualified-id <tt>T::result_type</tt> is
        valid and denotes a type (17.8.2), then <tt>result_type</tt> shall be a synonym for
        <tt>T::result_type</tt>;</del></li>
    <li><del>otherwise <tt>result_type</tt> shall not be defined.</del></li>
  </ol>
</ol>


<h4><del>D.8.2 Typedefs to Support Function Binders [depr.func.adaptor.typedefs]</del></h4>

<ol>
<li><del>
To enable old function adaptors to manipulate function objects that take one or
two arguments, many of the function objects in this International Standard correspondingly
provide <i>typedef-name</i>s <tt>argument_type</tt> and <tt>result_type</tt> for function
objects that take one argument and <tt>first_argument_type</tt>,
<tt>second_argument_type</tt>, and <tt>result_type</tt> for function objects
that take two arguments.
</del></li>

<li><del>
The following member names are defined in addition to names specified in Clause 23.14:
</del>

<blockquote><pre>
<del>namespace std {</del>
  <del>template&lt;class T&gt; struct owner_less&lt;shared_ptr&lt;T&gt; &gt; {</del>
    <del>using result_type          = bool;</del>
    <del>using first_argument_type  = shared_ptr&lt;T&gt;;</del>
    <del>using second_argument_type = shared_ptr&lt;T&gt;;</del>
  <del>};</del>

  <del>template&lt;class T&gt; struct owner_less&lt;weak_ptr&lt;T&gt; &gt; {</del>
    <del>using result_type          = bool;</del>
    <del>using first_argument_type  = weak_ptr&lt;T&gt;;</del>
    <del>using second_argument_type = weak_ptr&lt;T&gt;;</del>
  <del>};</del>

  <del>template &lt;class T&gt; class reference_wrapper {</del>
  <del>public :</del>
    <del>using result_type          = <i>see below</i>; <i>// not always defined</i></del>
    <del>using argument_type        = <i>see below</i>; <i>// not always defined</i></del>
    <del>using first_argument_type  = <i>see below</i>; <i>// not always defined</i></del>
    <del>using second_argument_type = <i>see below</i>; <i>// not always defined</i></del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct plus {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = T;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct minus {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = T;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct multiplies {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = T;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct divides {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = T;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct modulus {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = T;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct negate {</del>
    <del>using argument_type = T;</del>
    <del>using result_type   = T;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct equal_to {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = bool;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct not_equal_to {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = bool;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct greater {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = bool;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct less {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = bool;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct greater_equal {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = bool;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct less_equal {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = bool;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct logical_and {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = bool;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct logical_or {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = bool;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct logical_not {</del>
    <del>using argument_type = T;</del>
    <del>using result_type   = bool;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct bit_and {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = T;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct bit_or {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = T;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct bit_xor {</del>
    <del>using first_argument_type  = T;</del>
    <del>using second_argument_type = T;</del>
    <del>using result_type          = T;</del>
  <del>};</del>

  <del>template &lt;class T = void&gt; struct bit_not {</del>
    <del>using argument_type = T;</del>
    <del>using result_type   = T;</del>
  <del>};</del>

  <del>template&lt;class R, class T1&gt;</del>
  <del>class function&lt;R(T1)&gt; {</del>
  <del>public:</del>
    <del>using argument_type = T1;</del>
  <del>};</del>

  <del>template&lt;class R, class T1, class T2&gt;</del>
  <del>class function&lt;R(T1, T2)&gt; {</del>
  <del>public:</del>
    <del>using first_argument_type  = T1;</del>
    <del>using second_argument_type = T2;</del>
  <del>};</del>
<del>}</del>
</blockquote></pre>
</li>

<li><del><tt>reference_wrapper&lt;T&gt;</tt> has a weak result type (D.7.1). If
<tt>T</tt> is a function type, <tt>result_type</tt> shall be a synonym for the
return type of <tt>T</tt>.
</del></li>
<li><del>
The template specialization <tt>reference_wrapper&lt;T&gt;</tt> shall define
a nested type named <tt>argument_type</tt> as a synonym for <tt>T1</tt> only if
the type <tt>T</tt> is any of the following:
</del>
<ol>
<li><del>
&mdash; a function type or a pointer to function type taking one argument of
type <tt>T1</tt>
</del></li>
<li><del>
&mdash; a pointer to member function <tt>R T0::f <i>cv</i></tt> (where
<tt><i>cv</i></tt> represents the member function's <i>cv</i>-qualifiers); the
type <tt>T1</tt> is <tt><i>cv</i> T0*</tt>
</del></li>
<li><del>
&mdash; a class type where the <i>qualified-id</i> <tt>T::argument_type</tt> is valid
and denotes a type (14.8.2); the type <tt>T1</tt> is <tt>T::argument_type</tt>.
</del></li>
</ol></li>
<li><del>
The template instantiation <tt>reference_wrapper&lt;T&gt;</tt> shall define
two nested types named <tt>first_argument_type</tt> and
<tt>second_argument_type</tt> as synonyms for <tt>T1</tt> and <tt>T2</tt>,
respectively, only if the type <tt>T</tt> is any of the following:
</del>
<ol>
<li><del>
&mdash; a function type or a pointer to function type taking two arguments of
types <tt>T1</tt> and <tt>T2</tt>
</del></li>
<li><del>
&mdash; a pointer to member function <tt>R T0::f(T2) <i>cv</i></tt> (where
<tt><i>cv</i></tt> represents the member function's <i>cv</i>-qualifiers); the
type <tt>T1</tt> is <tt><i>cv</i> T0*</tt>
</del></li>
<li><del>
&mdash; a class type where the <i>qualified-id</i>s <tt>T::first_argument_type</tt>
and <tt>T::second_argument_type</tt> are both valid and both denote types
(14.8.2); the type <tt>T1</tt> is <tt>T::first_argument_type</tt> and the type
<tt>T2</tt> is <tt>T::second_argument_type</tt>.
</li>
</ol></li>
<li><del>
All enabled specializations <tt>hash&lt;Key&gt;</tt> of <tt>hash</tt> (23.14.15) provide
two nested types, <tt>result_type</tt> and <tt>argument_type</tt>, which shall be
synonyms for <tt>size_t</tt> and <tt>Key</tt>, respectively.
</del></li>
<li><del>
The forwarding call wrapper <tt>g</tt> returned by a call to
<tt>bind(f, bound_args...)</tt> (23.14.11.3) shall have a weak result type (D.7.1).
</del></li>
<li><del>
The forwarding call wrapper <tt>g</tt> returned by a call to
<tt>bind&lt;R&gt;(f, bound_args...)</tt> (23.14.11.3) shall have a nested type
<tt>result_type</tt> defined as a synonym for <tt>R</tt>.
</del></li>
<li><del>
The simple call wrapper returned from a call to
<tt>mem_fn(pm)</tt> shall have a nested type <tt>result_type</tt> that is a
synonym for the return type of <tt>pm</tt> when <tt>pm</tt> is a pointer to
member function.
</del></li>
<li><del>
The simple call wrapper returned from a call to
<tt>mem_fn(pm)</tt> shall define two nested types named
<tt>argument_type</tt> and <tt>result_type</tt> as synonyms for
<tt><i>cv</i> T*</tt> and <tt>Ret</tt>, respectively, when <tt>pm</tt> is a
pointer to member function with <i>cv</i>-qualifier <i>cv</i> and taking no
arguments, where <tt>Ret</tt> is <tt>pm</tt>'s return type.
</del></li>
<li><del>
The simple call wrapper returned from a call to
<tt>mem_fn(pm)</tt> shall define three nested types named
<tt>first_argument_type</tt>, <tt>second_argument_type</tt>, and
<tt>result_type</tt> as synonyms for <tt>cv T*</tt>, <tt>T1</tt>, and
<tt>Ret</tt>, respectively, when <tt>pm</tt> is a pointer to member function
with <i>cv</i>-qualifier <i>cv</i> and taking one argument of type <tt>T1</tt>,
where <tt>Ret</tt> is <tt>pm</tt>'s return type.
</del></li>
<li><del>
The following member names are defined in addition to names specified in Clause 26:
</del>
<blockquote><pre>
<del>namespace std {</del>
  <del>template &lt;class Key, class T, class Compare = less&lt;Key&gt;,</del>
            <del>class Allocator = allocator&lt;pair&lt;const Key, T&gt;&gt;&gt;</del>
  <del>class map {</del>
  <del>public:</del>
     <del>class value_compare {</del>
     <del>public:</del>
       <del>using result_type          = bool;</del>
       <del>using first_argument_type  = value_type;</del>
       <del>using second_argument_type = value_type;</del>
       <del>}</del>
    <del>};</del>
  <del>};</del>

  <del>template &lt;class Key, class T, class Compare = less&lt;Key&gt;,</del>
            <del>class Allocator = allocator&lt;pair&lt;const Key, T&gt;&gt;&gt;</del>
  <del>class multimap {</del>
  <del>public:</del>
     <del>class value_compare {</del>
     <del>public:</del>
       <del>using result_type          = bool;</del>
       <del>using first_argument_type  = value_type;</del>
       <del>using second_argument_type = value_type;</del>
    <del>};</del>
  <del>};</del>
<del>}</del>
</pre></blockquote>
</li>
</ol>

<h4><del>D.8.3 Negators [depr.negators]</del></h4>
<ol>
<li><del>
The header <tt>&lt;functional&gt;</tt> has the following additions:</del>
<blockquote><pre>
<del>namespace std {</del>
  <del>template &lt;class Predicate&gt; class unary_negate;</del>
  <del>template &lt;class Predicate&gt;</del>
    <del>constexpr unary_negate&lt;Predicate&gt; not1(const Predicate&amp;);</del>
  <del>template &lt;class Predicate&gt; class binary_negate;</del>
  <del>template &lt;class Predicate&gt;</del>
    <del>constexpr binary_negate&lt;Predicate&gt; not2(const Predicate&amp;);</del>
<del>}</del>
</pre></blockquote>
</li>
<li><del>
Negators <tt>not1</tt> and <tt>not2</tt> take a unary and a binary predicate,
respectively, and return their logical negations (8.3.1).
</del></li>

<p><pre><blockquote>
   <del>template &lt;class Predicate&gt;</del>
     <del>class unary_negate {</del>
   <del>public:</del>
     <del>constexpr explicit unary_negate(const Predicate&amp; pred);</del>
     <del>constexpr bool operator()(const typename Predicate::argument_type&amp; x) const;</del>
     <del>using argument_type = typename Predicate::argument_type;</del>
     <del>using result_type   = bool;</del>
   <del>};</del>
</blockquote></pre></p>

<li><del>
<tt>operator()</tt> returns <tt>!pred(x)</tt>.
</del></li>

<p><pre><blockquote>
 <del>template &lt;class Predicate&gt;</del>
     <del>constexpr unary_negate&lt;Predicate&gt; not1(const Predicate&amp; pred);</del>
</blockquote></pre></p>

<li><del>
<i>Returns:</i> <tt>unary_negate&lt;Predicate&gt;(pred)</tt>.
</del></li>

<p><pre><blockquote>
  <del>template &lt;class Predicate&gt;</del>
  <del>class binary_negate {</del>
  <del>public:</del>
    <del>constexpr explicit binary_negate(const Predicate&amp; pred);</del>
    <del>constexpr bool operator()(const typename Predicate::first_argument_type&amp; x,</del>
                              <del>const typename Predicate::second_argument_type&amp; y) const;</del>
    <del>using first_argument_type = typename Predicate::first_argument_type;</del>
    <del>using second_argument_type = typename Predicate::second_argument_type;</del>
    <del>using result_type = bool;</del>
  <del>};</del>
</blockquote></pre></p>

<li><del>
<tt>operator()</tt> returns <tt>!pred(x,y)</tt>.
</del></li>

<p><pre><blockquote>
<del>template &lt;class Predicate&gt;</del>
  <del>constexpr binary_negate&lt;Predicate&gt; not2(const Predicate&amp; pred);</del>
</blockquote></pre></p>

<li><del>
<i>Returns:</i> <tt>binary_negate&lt;Predicate&gt;(pred)</tt>.
</del></li>
</ol>

</ol>

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

</blockquote>

<blockquote class="recommend">
<b>Weak recommendation:</b>
Remove only the negators from C++20.
</blockquote>

<blockquote>
<h4><del>D.8.3 Negators [depr.negators]</del></h4>
<ol>
<li><del>
The header <tt>&lt;functional&gt;</tt> has the following additions:</del>
</del></li>
<blockquote><pre>
<del>namespace std {</del>
  <del>template &lt;class Predicate&gt; class unary_negate;</del>
  <del>template &lt;class Predicate&gt;</del>
    <del>constexpr unary_negate&lt;Predicate&gt; not1(const Predicate&amp;);</del>
  <del>template &lt;class Predicate&gt; class binary_negate;</del>
  <del>template &lt;class Predicate&gt;</del>
    <del>constexpr binary_negate&lt;Predicate&gt; not2(const Predicate&amp;);</del>
<del>}</del>
</pre></blockquote>
<li><del>
Negators <tt>not1</tt> and <tt>not2</tt> take a unary and a binary predicate,
respectively, and return their logical negations (8.3.1).
</del></li>

<pre><blockquote>
   <del>template &lt;class Predicate&gt;</del>
     <del>class unary_negate {</del>
   <del>public:</del>
     <del>constexpr explicit unary_negate(const Predicate&amp; pred);</del>
     <del>constexpr bool operator()(const typename Predicate::argument_type&amp; x) const;</del>
     <del>using argument_type = typename Predicate::argument_type;</del>
     <del>using result_type   = bool;</del>
   <del>};</del>
</blockquote></pre>

<li><del>
<tt>operator()</tt> returns <tt>!pred(x)</tt>.
</del></li>

<pre><blockquote>
 <del>template &lt;class Predicate&gt;</del>
     <del>constexpr unary_negate&lt;Predicate&gt; not1(const Predicate&amp; pred);</del>
</blockquote></pre>

<li><del>
<i>Returns:</i> <tt>unary_negate&lt;Predicate&gt;(pred)</tt>.
</del></li>

<pre><blockquote>
  <del>template &lt;class Predicate&gt;</del>
  <del>class binary_negate {</del>
  <del>public:</del>
    <del>constexpr explicit binary_negate(const Predicate&amp; pred);</del>
    <del>constexpr bool operator()(const typename Predicate::first_argument_type&amp; x,</del>
                              <del>const typename Predicate::second_argument_type&amp; y) const;</del>
    <del>using first_argument_type = typename Predicate::first_argument_type;</del>
    <del>using second_argument_type = typename Predicate::second_argument_type;</del>
    <del>using result_type = bool;</del>
  <del>};</del>
</blockquote></pre>

<li><del>
<tt>operator()</tt> returns <tt>!pred(x,y)</tt>.
</del></li>

<pre><blockquote>
<del>template &lt;class Predicate&gt;</del>
  <del>constexpr binary_negate&lt;Predicate&gt; not2(const Predicate&amp; pred);</del>
</blockquote></pre>

<li><del>
<i>Returns:</i> <tt>binary_negate&lt;Predicate&gt;(pred)</tt>.
</del></li>
</ol>

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

</blockquote>


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


<h3><a name="3.9">D.9 The default allocator [depr.default.allocator]</a></h3>
<p>
One surprising issue turned up with an implementation that eagerly removed
the deprecated names.  It turns out that there are platforms where <tt>size_t</tt>
and <tt>ptrdiff_t</tt> are not signed/unsigned variations on the same underlying
type, so relying on the default type computation through <tt>allocator_traits</tt>
produces ABI incompatibilities.  It appears reasonably safe to remove the other
members once direct use has diminished.  This would be a noticable compatibility
hurdle for containers trying to retain compatibility with both C++03 code and
C++20, due to the lack of <tt>allocator_traits</tt> in that earlier standard.
However, most of a decade will have passed since the publication of C++11 by the
time C++20 is published, and that may be deemed sufficient time to address
compatibility concerns.
</p>
<p>
<tt>allocator&lt;void&gt;</tt> does not serve a useful compatibility
purpose, and should safely be removed.  There are no special names to
be reserved as zombies, as all removed identifiers continue to be used
throughout the library.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b> Undeprecate <tt>std::allocator&lt;T&gt;::size_type</tt>
and <tt>std::allocator&lt;T&gt;::difference_type</tt>, and remove the remaining
deprecated parts from the C++20 standard:
</blockquote>

<blockquote>
<h4>23.10.9 The default allocator [default.allocator]</h4>
<blockquote><pre>
namespace std {
  template &lt;class T&gt; class allocator {
  public:
    using value_type      = T;
    <ins>using size_type       = size_t;</ins>
    <ins>using difference_type = ptrdiff_t;</ins>
    using is_always_equal = true_type;
    using propagate_on_container_move_assignment = true_type;

    allocator() noexcept;
    allocator(const allocator&amp;) noexcept;
    template <class U> allocator(const allocator&lt;U&gt;&amp;) noexcept;
    ~allocator();

    T* allocate(size_t n);
    void deallocate(T* p, size_t n);
  };
}
</pre></blockquote>

<h4><del>D.9 The default allocator [depr.default.allocator]</del></h4>
<ol>
<li><del>The following members are defined in addition to those specified in Clause 20:</del></li>
<pre>
<del>namespace std {</del>
  <del>template &lt;&gt; class allocator&lt;void&gt; {</del>
  <del>public:</del>
    <del>using value_type    = void;</del>
    <del>using pointer       = void*;</del>
    <del>using const_pointer = const void*;</del>
    <del><i>// reference-to-void members are impossible.</i></del>
    <del>template &lt;class U&gt; struct rebind { using other = allocator&lt;U&gt;; };</del>
  <del>};</del>

  <del>template &lt;class T&gt; class allocator {</del>
  <del>public:</del>
    <del>using size_type       = size_t;</del>
    <del>using difference_type = ptrdiff_t;</del>
    <del>using pointer         = T*;</del>
    <del>using const_pointer   = const T*;</del>
    <del>using reference       = T&amp;;</del>
    <del>using const_reference = const T&amp;;</del>
    <del>template &lt;class U&gt; struct rebind { using other = allocator&lt;U&gt;; };</del>

    <del>T* address(reference x) const noexcept;</del>
    <del>const T* address(const_reference x) const noexcept;</del>

    <del>T* allocate(size_t, const void* hint);</del>

    <del>template&lt;class U, class... Args&gt;</del>
      <del>void construct(U* p, Args&amp;&amp;... args);</del>
    <del>template &lt;class U&gt;</del>
      <del>void destroy(U* p);</del>

    <del>size_t max_size() const noexcept;</del>
  <del>};</del>
<del>}</del>
</pre>

<pre><del>T* address(reference x) const noexcept;</del>
<del>const T* address(const_reference x) const noexcept;</del></pre>
<li><del>
<i>Returns:</i> The actual address of the object referenced by <tt>x</tt>, even
in the presence of an overloaded <tt>operator&amp;</tt>.
</del></li>

<pre><del>T* allocate(size_t, const void* hint);</del></pre>
<li><del>
<i>Returns:</i> A pointer to the initial element of an array of storage of size
<tt>n * sizeof(T)</tt>, aligned appropriately for objects of type <tt>T</tt>.
It is implementation-defined whether over-aligned types are supported (3.11).
</del></li>
<li><del>
<i>Remark:</i> the storage is obtained by calling
<tt>::operator new(std::size_t)</tt> (18.6.1), but it is unspecified when or
how often this function is called.
</del></li>
<li><del>
<i>Throws:</i> <tt>bad_alloc</tt> if the storage cannot be obtained.
</del></li>

<pre>
<del>template &lt;class U, class... Args&gt;</del>
  <del>void construct(U* p, Args&amp;&amp;... args);</del>
</pre>
<li><del>
<i>Effects:</i> <tt>::new((void *)p) U(std::forward&lt;Args&gt;(args)...)</tt>
</del></li>

<pre>
<del>template &lt;class U&gt;</del>
  <del>void destroy(U* p);</del>
</pre>
<li><del>
<i>Effects:</i> <tt>p-&gt;~U()</tt>
</del></li>

<pre><del>size_type max_size() const noexcept;</del></pre>
<li><del>
<i>Returns:</i> The largest value <tt>N</tt> for which the call
<tt>allocate(N)</tt> might succeed.
</del></li>
</ol>

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


<blockquote class="recommend">
<b>Weak recommendation:</b>
Undeprecate <tt>std::allocator&lt;T&gt;::size_type</tt> and
<tt>std::allocator&lt;T&gt;::difference_type</tt>, and remove
(just) <tt>std::allocator&lt;void&gt;</tt>:
</blockquote>

<blockquote>
<h4>23.10.9 The default allocator [default.allocator]</h4>
<blockquote><pre>
namespace std {
  template &lt;class T&gt; class allocator {
  public:
    using value_type      = T;
    <ins>using size_type       = size_t;</ins>
    <ins>using difference_type = ptrdiff_t;</ins>
    using is_always_equal = true_type;
    using propagate_on_container_move_assignment = true_type;

    allocator() noexcept;
    allocator(const allocator&amp;) noexcept;
    template <class U> allocator(const allocator&lt;U&gt;&amp;) noexcept;
    ~allocator();

    T* allocate(size_t n);
    void deallocate(T* p, size_t n);
  };
}
</pre></blockquote>

<h4>D.9 The default allocator [depr.default.allocator]</h4>
<ol>
<li>The following members are defined in addition to those specified in Clause 20:</li>
<pre>
namespace std {
  <del>template &lt;&gt; class allocator&lt;void&gt; {</del>
  <del>public:</del>
    <del>using value_type    = void;</del>
    <del>using pointer       = void*;</del>
    <del>using const_pointer = const void*;</del>
    <del><i>// reference-to-void members are impossible.</i></del>
    <del>template &lt;class U&gt; struct rebind { using other = allocator&lt;U&gt;; };</del>
  <del>};</del>

  template &lt;class T&gt; class allocator {
  public:
    <del>using size_type       = size_t;</del>
    <del>using difference_type = ptrdiff_t;</del>
    using pointer         = T*;
    using const_pointer   = const T*;
    using reference       = T&amp;;
    using const_reference = const T&amp;;
    template &lt;class U&gt; struct rebind { using other = allocator&lt;U&gt;; };

    T* address(reference x) const noexcept;
    const T* address(const_reference x) const noexcept;

    T* allocate(size_t, const void* hint);

    template&lt;class U, class... Args&gt;
      void construct(U* p, Args&amp;&amp;... args);
    template &lt;class U&gt;
      void destroy(U* p);

    size_t max_size() const noexcept;
  };
}
</pre>
</ol>	
</blockquote>

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


</blockquote>


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


<h3><a name="3.10">D.10 Raw storage iterator [depr.storage.iterator]</a></h3>
<p>
<tt>raw_storage_iterator</tt> is a limited facility with several shortcomings
that are unlikely to be addressed.  The most obvious is that in its intended
use in an algorithm, there is no clear way to identify how many items have
been constructed and would be cleaned up if a constructor throws.  Such a
fundamentally unsafe type has no place in a modern standard library.
</p>

<p>
Additional concerns include that it does not support allocators, and does not
call <tt>allocator_traits::construct</tt> to initialize elements, making it
unsuitable as an implementation detail for the majority of containers.
</p>

<p>
To continue as an integral part of the C++ standard library it should acquire
external deduction guides to deduce <tt>T</tt> from the <tt>value_type</tt> of
the passed <tt>OutputIterator</tt>, but it does not seem worth the effort to
revive.
</p>

<p>
The class template may live on a while longer as a zombie name, allowing
vendors to wean customers off at their own pace, but this class no longer
belongs in the C++ Standard Library.
</p>

<blockquote class="recommend">
<b>Strong recommendation:</b>
remove the deprecated iterator from C++20.
</blockquote>

<blockquote>
<h4>20.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization: <tt>auto_ptr</tt>, <tt>binary_function</tt>, <tt>bind1st</tt>,
<tt>bind2nd</tt>, <tt>binder1st</tt>, <tt>binder2nd</tt>,
<tt>const_mem_fun1_ref_t</tt>, <tt>const_mem_fun1_t</tt>,
<tt>const_mem_fun_ref_t</tt>, <tt>const_mem_fun_t</tt>,
<tt>get_unexpected</tt>, <tt>mem_fun1_ref_t</tt>, <tt>mem_fun1_t</tt>,
<tt>mem_fun_ref_t</tt>, <tt>mem_fun_ref</tt>, <tt>mem_fun_t</tt>,
<tt>mem_fun</tt>, <tt>pointer_to_binary_function</tt>,
<tt>pointer_to_unary_function</tt>, <tt>ptr_fun</tt>, <tt>random_shuffle</tt>,
<ins><tt>raw_storage_iterator</tt>,</ins> <tt>set_unexpected</tt>,
<tt>unary_function</tt>, <tt>unexpected</tt>, and <tt>unexpected_handler</tt>.
</li>
</ol>

<h4><del>D.10 Raw storage iterator [depr.storage.iterator]</del></h4>
<ol>
<p><del>
The header <tt>&lt;memory&gt;</tt> has the following addition:</del>
</del></p>

<pre>
  <del>namespace std {</del>
    <del>template &lt;class OutputIterator, class T&gt;</del>
    <del>class raw_storage_iterator {</del>
    <del>public:</del>
      <del>using iterator_category = output_iterator_tag;</del>
      <del>using value_type        = void;</del>
      <del>using difference_type   = void;</del>
      <del>using pointer           = void;</del>
      <del>using reference         = void;</del>

      <del>explicit raw_storage_iterator(OutputIterator x);</del>

      <del>raw_storage_iterator&amp; operator*();</del>
      <del>raw_storage_iterator&amp; operator=(const T&amp; element);</del>
      <del>raw_storage_iterator&amp; operator=(T&amp;&amp; element);</del>
      <del>raw_storage_iterator&amp; operator++();</del>
      <del>raw_storage_iterator  operator++(int);</del>
      <del>OutputIterator base() const;</del>
    <del>};</del>
  <del>}</del>
</pre>

<li><del>
<tt>raw_storage_iterator</tt> is provided to enable algorithms to store their
results into uninitialized memory. The template parameter
<tt>OutputIterator</tt> is required to have its <tt>operator*</tt> return an
object for which <tt>operator&amp;</tt> is defined and returns a pointer to
<tt>T</tt>, and is also required to satisfy the requirements of an output
iterator (24.2.4).
</del></li>

<pre>
<del>explicit raw_storage_iterator(OutputIterator x);</del>
</pre>
<li><del>
<i>Effects:</i> Initializes the iterator to point to the same value to which
<tt>x</tt> points.
</del></li>

<pre>
<del>raw_storage_iterator&amp; operator*();</del>
</pre>
<li><del>
<i>Returns:</i> <tt>*this</tt>
</del></li>

<pre>
<del>raw_storage_iterator&amp; operator=(const T&amp; element);</del>
</pre>
<li><del>
<i>Requires:</i> <tt>T</tt> shall be <tt>CopyConstructible</tt>.
</del></li>
<li><del>
<i>Effects:</i> Constructs a value from <tt>element</tt> at the location to
which the iterator points.
</del></li>
<li><del>
<i>Returns:</i> A reference to the iterator.
</del></li>

<pre>
<del>raw_storage_iterator&amp; operator=(T&amp;&amp; element);</del>
</pre>
<li><del>
<i>Requires:</i> <tt>T</tt> shall be <tt>MoveConstructible</tt>.
</del></li>
<li><del>
<i>Effects:</i> Constructs a value from <tt>std::move(element)</tt> at the
location to which the iterator points.
</del></li>
<li><del>
<i>Returns:</i> A reference to the iterator.
</del></li>

<pre>
<del>raw_storage_iterator&amp; operator++();</del>
</pre>
<li><del>
<i>Effects:</i> Pre-increment: advances the iterator and returns a reference to
the updated iterator.
</del></li>

<pre>
<del>raw_storage_iterator operator++(int);</del>
</pre>
<li><del>
<i>Effects:</i> Post-increment: advances the iterator and returns the old value
of the iterator.
</del></li>

<pre>
<del>OutputIterator base() const;</del>
</pre>
<li><del>
<i>Returns:</i> An iterator of type <tt>OutputIterator</tt> that points to the
same value as <tt>*this</tt> points to.
</del></li>
</ol>

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

</blockquote>


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

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


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


<h3><a name="3.11">D.11 Temporary buffers [depr.temporary.buffer]</a></h3>

<blockquote class="recommend">
<b>Strong recommendation:</b>
remove the awkward API.
</blockquote>

<blockquote>
<h4>20.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization: <tt>auto_ptr</tt>, <tt>binary_function</tt>, <tt>bind1st</tt>,
<tt>bind2nd</tt>, <tt>binder1st</tt>, <tt>binder2nd</tt>,
<tt>const_mem_fun1_ref_t</tt>, <tt>const_mem_fun1_t</tt>,
<tt>const_mem_fun_ref_t</tt>, <tt>const_mem_fun_t</tt>,
<ins><tt>get_temporary_buffer</tt>,</ins> <tt>get_unexpected</tt>,
<tt>mem_fun1_ref_t</tt>, <tt>mem_fun1_t</tt>, <tt>mem_fun_ref_t</tt>,
<tt>mem_fun_ref</tt>, <tt>mem_fun_t</tt>, <tt>mem_fun</tt>,
<tt>pointer_to_binary_function</tt>, <tt>pointer_to_unary_function</tt>,
<tt>ptr_fun</tt>, <tt>random_shuffle</tt>,
<ins><tt>return_temporary_buffer</tt>,</ins> <tt>set_unexpected</tt>,
<tt>unary_function</tt>, <tt>unexpected</tt>, and <tt>unexpected_handler</tt>.
</li>
</ol>

<h3><del>D.11 Temporary buffers [depr.temporary.buffer]</del></h3>
<ol>
<li><del>
The header <tt>&lt;memory&gt;</tt> has the following additional functions:</del>
</del></li>
<blockquote><pre>
<del>namespace std {</del>
  <del><i>// 20.9.11, temporary buffers:</i></del>
  <del>template &lt;class T&gt;</del>
    <del>pair&lt;T*, ptrdiff_t&gt; get_temporary_buffer(ptrdiff_t n) noexcept;</del>
  <del>template &lt;class T&gt;</del>
    <del>void return_temporary_buffer(T* p);</del>
<del>}</del>
</pre></blockquote>

<pre>
<del>template &lt;class T&gt;</del>
  <del>pair&lt;T*, ptrdiff_t&gt; get_temporary_buffer(ptrdiff_t n) noexcept;</del>
</pre>
<li><del>
<i>Effects:</i> Obtains a pointer to uninitialized, contiguous storage for
<i>N</i> adjacent objects of type <tt>T</tt>, for some non-negative number
<i>N</i>. It is implementation-defined whether over-aligned types are supported
(3.11).
</del></li>
<li><del>
<i>Remarks:</i> Calling <tt>get_temporary_buffer</tt> with a positive number
<tt>n</tt> is a non-binding request to return storage for <tt>n</tt> objects of
type <tt>T</tt>. In this case, an implementation is permitted to return instead
storage for a non-negative number <i>N</i> of such objects, where
<i>N</i><tt>!= n</tt> (including <i>N</i><tt> == 0</tt>). [ <i>Note:</i> The
request is non-binding to allow latitude for implementation-specific
optimizations of its memory management.  - <i>end note</i> ]
</del></li>
<li><del>
<i>Returns:</i> If <tt>n &lt;= 0</tt> or if no storage could be obtained,
returns a pair <tt>P</tt> such that <tt>P.first</tt> is a null pointer value
and <tt>P.second == 0</tt>; otherwise returns a pair <tt>P</tt> such that
<tt>P.first</tt> refers to the address of the uninitialized storage and
<tt>P.second</tt> refers to its capacity <i>N</i> (in the units of
<tt>sizeof(T)</tt>).
</del></li>
</ol>

<pre>
<del>template &lt;class T&gt; void return_temporary_buffer(T* p);</del>
</pre>
<ol>
<li><del>
<i>Effects:</i> Deallocates the storage referenced by <tt>p</tt>.
</del></li>
<li><del>
<i>Requires:</i> <tt>p</tt> shall be a pointer value returned by an earlier
call to <tt>get_temporary_buffer</tt> that has not been invalidated by an
intervening call to <tt>return_temporary_buffer(T*)</tt>.
</del></li>
<li><del>
<i>Throws:</i> Nothing.
</del></li>
</ol>
</blockquote>

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


<blockquote class="recommend">
<b>Weak recommendation:</b>
add sufficient facilities for safe use that the facility can be undeprecated.
</blockquote>

<blockquote class="note">
Details are deferred to a follow-up paper, if desired.
</blockquote>


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


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

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

<blockquote>
<h4>20.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization: <tt>auto_ptr</tt>, <tt>binary_function</tt>, <tt>bind1st</tt>,
<tt>bind2nd</tt>, <tt>binder1st</tt>, <tt>binder2nd</tt>,
<tt>const_mem_fun1_ref_t</tt>, <tt>const_mem_fun1_t</tt>,
<tt>const_mem_fun_ref_t</tt>, <tt>const_mem_fun_t</tt>,
<tt>get_unexpected</tt>, <ins><tt>is_literal_type</tt>,
<tt>is_literal_type_v</tt>,</ins>
<tt>mem_fun1_ref_t</tt>, <tt>mem_fun1_t</tt>, <tt>mem_fun_ref_t</tt>,
<tt>mem_fun_ref</tt>, <tt>mem_fun_t</tt>, <tt>mem_fun</tt>,
<tt>pointer_to_binary_function</tt>, <tt>pointer_to_unary_function</tt>,
<tt>ptr_fun</tt>, <tt>random_shuffle</tt>, <ins><tt>result_of</tt>,
<tt>result_of_t</tt>,</ins> <tt>set_unexpected</tt>,
<tt>unary_function</tt>, <tt>unexpected</tt>, and <tt>unexpected_handler</tt>.
</li>
</ol>

<h4><del>D.12 Deprecated Type Traits [depr.meta.type]</del></h4>
<ol>
<li><del>
The header <tt>&lt;type_traits&gt;</tt> has the following additions:</del>
</del></li>

<blockquote><pre>
<del>namespace std {</del>
  <del>template &lt;class T&gt; struct is_literal_type;</del>

  <del>template &lt;class T&gt; constexpr bool is_literal_type_v = is_literal_type&lt;T&gt;::value;</del>

  <del>template &lt;class&gt; struct result_of; // not defined</del>
  <del>template &lt;class Fn, class... ArgTypes&gt; struct result_of&lt;Fn(ArgTypes...)&gt;;</del>

  <del>template &lt;class T&gt; using result_of_t = typename result_of&lt;T&gt;::type;</del>
<del>}</del>
</pre></blockquote>

<li><del>
<i>Requires:</i> For <tt>is_literal_type</tt>,
<tt>remove_all_extents_t&lt;T&gt;</tt> shall be a complete type or <i>cv</i>
<tt>void</tt>.  For <tt>result_of&lt;Fn(ArgTypes...)&gt;</tt>, <tt>Fn</tt> and
all types in the parameter pack <tt>ArgTypes</tt> shall be complete types,
<i>cv</i> <tt>void</tt>, or arrays of unknown bound.
</del></li>

<li><del>
<tt>is_literal_type</tt> is a <tt>UnaryTypeTrait</tt> (23.15.1) with a
base-characteristic of <tt>true_type</tt> if <tt>T</tt> is a literal type
(3.9), and <tt>false_type</tt> otherwise.  The partial specialization
<tt>result_of&lt;Fn(ArgTypes...)&gt;</tt> is a <tt>TransformationTrait</tt>
whose member typedef <tt>type</tt> is defined if and only if
<tt>invoke_result&lt;Fn, ArgTypes...&gt;::type</tt> is defined. If
<tt>type</tt> is defined, it names the same type as <tt>invoke_result_t&lt;Fn,
ArgTypes...&gt;</tt>.
</del></li>

<li><del>
The behavior of a program that adds specializations for
<tt>is_literal_type</tt> or <tt>is_literal_type_v</tt> is undefined.
</del></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.
</blockquote>


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


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

<blockquote class="recommend">
<b>Strong recommendation:</b>
enhance <tt>iterator_traits</tt> with implicit deductions of each
nested name, to better facilitate removal of this feature.
</blockquote>

<blockquote class="note">
Details are deferred to a follow-up paper, if desired, and apply
the edit below.
</blockquote>

<blockquote class="recommend">
<b>Weak recommendation:</b>
remove this awkward class template, whether or not an improved
deduction facility becomes available.
</blockquote>

<blockquote>
<h4>20.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization: <tt>auto_ptr</tt>, <tt>binary_function</tt>, <tt>bind1st</tt>,
<tt>bind2nd</tt>, <tt>binder1st</tt>, <tt>binder2nd</tt>,
<tt>const_mem_fun1_ref_t</tt>, <tt>const_mem_fun1_t</tt>,
<tt>const_mem_fun_ref_t</tt>, <tt>const_mem_fun_t</tt>,
<tt>get_unexpected</tt>, <ins><tt>iterator</tt>,</ins> <tt>mem_fun1_ref_t</tt>,
<tt>mem_fun1_t</tt>, <tt>mem_fun_ref_t</tt>, <tt>mem_fun_ref</tt>,
<tt>mem_fun_t</tt>, <tt>mem_fun</tt>, <tt>pointer_to_binary_function</tt>,
<tt>pointer_to_unary_function</tt>, <tt>ptr_fun</tt>, <tt>random_shuffle</tt>,
<tt>set_unexpected</tt>, <tt>unary_function</tt>, <tt>unexpected</tt>, and
<tt>unexpected_handler</tt>.
</li>
</ol>

<h4><del>D.13 Deprecated iterator primitives [depr.iterator.primitives]</del></h4>
<h5><del>D.13.1 Basic iterator [depr.iterator.basic]</del></h5>
<ol>
<li><del>
The header <tt>&lt;iterator&gt;</tt> 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>


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


<h3><a name="3.14">D.14 Deprecated <tt>shared_ptr</tt> observers [depr.util.smartptr.shared.obs]</a></h3>

<blockquote class="recommend">
<b>Strong recommendation:</b>
Remove misleading function, as <tt>use_count</tt> remains for single-threaded use.
</blockquote>

<blockquote>
<h4><del>D.13 Deprecated shared_ptr observers [depr.util.smartptr.shared.obs]</del></h4>
<ol>
<li><del>
The following member is defined in addition to those members specified in 23.11.2.2:
</del></li>
<blockquote><pre>
<del>namespace std {</del>
  <del>template<class T> class shared_ptr {</del>
  <del>public:</del>
    <del>bool unique() const noexcept;</del>
  <del>};</del>
<del>}</del>
</pre></blockquote>
<blockquote><pre>
<del>bool unique() const noexcept;</del></del>
</pre></blockquote>
<li><del>
<i>Returns:</i> <tt>use_count() == 1</tt>.
</del></li>
</blockquote>

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


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

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


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


<h3><a name="3.15">D.15 Standard code conversion facets [depr.locale.stdcvt]</a></h3>

<blockquote class="recommend">
<b>Strong recommendation:</b>
Remove the header <tt>&lt;codecvt&gt;</tt>; retain all names, including header name,
as zombies.
</blockquote>

<blockquote>
<h4>20.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization: <tt>auto_ptr</tt>, <tt>binary_function</tt>, <tt>bind1st</tt>,
<tt>bind2nd</tt>, <tt>binder1st</tt>, <tt>binder2nd</tt>, <ins><tt>codecvt_mode</tt>,
<tt>codecvt_utf16</tt>, <tt>codecvt_utf8</tt>, <tt>codecvt_utf8_utf16</tt>,</ins>
<tt>const_mem_fun1_ref_t</tt>, <tt>const_mem_fun1_t</tt>,
<tt>const_mem_fun_ref_t</tt>, <tt>const_mem_fun_t</tt>, <ins><tt>consume_header</tt>,
<tt>generate_header</tt>,</ins> <tt>get_unexpected</tt>,
<ins><tt>little_endian</tt>,</ins> <tt>mem_fun1_ref_t</tt>, <tt>mem_fun1_t</tt>,
<tt>mem_fun_ref_t</tt>, <tt>mem_fun_ref</tt>, <tt>mem_fun_t</tt>,
<tt>mem_fun</tt>, <tt>pointer_to_binary_function</tt>,
<tt>pointer_to_unary_function</tt>, <tt>ptr_fun</tt>, <tt>random_shuffle</tt>,
<tt>set_unexpected</tt>, <tt>unary_function</tt>, <tt>unexpected</tt>, and
<tt>unexpected_handler</tt>.
</li>

<li><ins>
The header name <tt>&lt;codecvt&gt;</tt> is reserved for previous standardization.
</ins></li>
</ol>

<h3><del>D.14 Standard code conversion facets [depr.locale.stdcvt]</del></h3>
<h4><del>D.14.1 Header <tt>&lt;codecvt&gt;</tt> synopsis [depr.codecvt.syn]</del></h4>
<ol>
<li><del>
The header <tt>&lt;codecvt&gt;</tt> provides code conversion facets for various
character encodings.
</del></li>
</ol>
<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.14.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>:
<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
UCS4 (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
UCS4 (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>
See also: ISO/IEC 10646-1:1993.
</del></li>
</ol>


</blockquote>

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

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

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


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


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

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


<blockquote>
<h4>20.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization: <tt>auto_ptr</tt>, <tt>binary_function</tt>, <tt>bind1st</tt>,
<tt>bind2nd</tt>, <tt>binder1st</tt>, <tt>binder2nd</tt>,
<tt>const_mem_fun1_ref_t</tt>, <tt>const_mem_fun1_t</tt>,
<tt>const_mem_fun_ref_t</tt>, <tt>const_mem_fun_t</tt>,
<tt>get_unexpected</tt>, <tt>mem_fun1_ref_t</tt>, <tt>mem_fun1_t</tt>,
<tt>mem_fun_ref_t</tt>, <tt>mem_fun_ref</tt>, <tt>mem_fun_t</tt>,
<tt>mem_fun</tt>, <tt>pointer_to_binary_function</tt>,
<tt>pointer_to_unary_function</tt>, <tt>ptr_fun</tt>, <tt>random_shuffle</tt>,
<tt>set_unexpected</tt>, <tt>unary_function</tt>, <tt>unexpected</tt>, <del>and</del>
<tt>unexpected_handler</tt><ins>, <tt>wbuffer_convert</tt>, and
<tt>wstring_convert</tt></ins>.
</li>

<li><ins>
The following names are reserved as member functions for previous
standardization, and may not be used as names for function-like macros in
portable code: <tt>converted</tt>, <tt>from_bytes</tt>, and
<tt>to_bytes</tt>.
</ins></li>

</ol>

<h4><del>D.16.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 Wide_alloc = allocator&lt;Elem&gt;,</del>
          <del>class Byte_alloc = 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;, Byte_alloc&gt;;</del>
    <del>using wide_string = basic_string&lt;Elem, char_traits&lt;Elem&gt;, Wide_alloc&gt;;</del>
    <del>using state_type  = typename Codecvt::state_type;</del>
    <del>using int_type    = typename wide_string::traits_type::int_type;</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;</del>
    <del>wide_string wide_err_string;</del>
    <del>Codecvt* cvtptr;</del>
    <del>state_type cvtstate;</del>
    <del>size_t cvtcount;</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;, Wide_alloc&gt;</tt> and
byte string objects of class
<tt>basic_string&lt;char, char_traits&lt;char&gt;, Byte_alloc&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;, Byte_alloc&gt;;</del>
</blockquote></pre>
<li><del>
The type shall be a synonym for
<tt>basic_string&lt;char, char_traits&lt;char&gt;, Byte_alloc&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;, Wide_alloc&gt;;</del>
</blockquote></pre>
<li><del>
The type shall be a synonym for
<tt>basic_string&lt;Elem, char_traits&lt;Elem&gt;, Wide_alloc&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.16.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>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>
take no action yet.
</blockquote>

<blockquote class="note">
No change.
</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, epitomised 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>


<h2><a name="5.0">5 Formal Wording</a></h2>
<p>
For now, this section does not contain any wording for feature removal or
undeprecation, as the proposed drafting for (re)moving each facility is
attached to the subsection reviewing those features.  Once the relevant
evolution groups have agreed which removals should proceed, the wording will be
consolidated here as a simpler direction for the project editor(s) to apply.
</p>
<p>
Below is a minimal set of edits that fix unreported issues with the current
standard, that bring it much closer to its original intent wrt some of the
features explored above.  These changes are proposed regardless of the
acceptance or rejection of any (or all) of the suggestions above.
</p>

<blockquote class="note">
Add missing zombies from prior standards:
</blockquote>

<blockquote>
<h4>20.5.4.3.1 Zombie names [zombie.names]</h4>
<ol>
<li>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization: <tt>auto_ptr</tt>, <ins><tt>auto_ptr_ref</tt>,</ins>
<tt>binary_function</tt>, <tt>bind1st</tt>, <tt>bind2nd</tt>,
<tt>binder1st</tt>, <tt>binder2nd</tt>, <tt>const_mem_fun1_ref_t</tt>,
<tt>const_mem_fun1_t</tt>, <tt>const_mem_fun_ref_t</tt>,
<tt>const_mem_fun_t</tt>, <tt>get_unexpected</tt>, <ins><tt>gets</tt>,</ins>
<tt>mem_fun1_ref_t</tt>, <tt>mem_fun1_t</tt>, <tt>mem_fun_ref_t</tt>,
<tt>mem_fun_ref</tt>, <tt>mem_fun_t</tt>, <tt>mem_fun</tt>,
<tt>pointer_to_binary_function</tt>, <tt>pointer_to_unary_function</tt>,
<tt>ptr_fun</tt>, <tt>random_shuffle</tt>, <tt>set_unexpected</tt>,
<tt>unary_function</tt>, <tt>unexpected</tt>, and <tt>unexpected_handler</tt>.
</li>

<li><ins>
The following names are reserved as member types for previous standardization,
and may not be used as names for object-like macros in portable code:
<tt>io_state</tt>, <tt>open_mode</tt>, and <tt>seek_dir</tt>
</ins></li>

<li><ins>
The following name is reserved as a member function for previous
standardization, and may not be used as names for function-like macros in
portable code: <tt>stossc</tt>.
</ins></li>
</ol>
</blockquote>

<blockquote class="note">
Provide default copy operations for the following classes, so that they
no longer rely on deprecated copy constructor/assignment generation,
even if the feature is not removed:
<ul>
  <li><tt>bitset&lt;N&gt;::reference</tt> - assign, no copy ctor</li>
  <li><tt>allocator</tt> - copy ctor, no assignment</li>
  <li><tt>pmr::memory_resource</tt> - dtor only, no copy/assign</li>
  <li><tt>vector&lt;bool&gt;::reference</tt> - assign, no copy ctor</li>
  <li><tt>istream_iterator</tt> - copy ctor, no assignment</li>
  <li><tt>ostream_iterator</tt> - copy ctor, no assignment</li>
  <li><tt>istreambuf_iterator</tt> - copy ctor, no assignment</li>
  <li><tt>complex&lt;float&gt;</tt> - assign, no copy ctor</li>
  <li><tt>complex&lt;double&gt;</tt> - assign, no copy ctor</li>
  <li><tt>complex&lt;long double&gt;</tt> - assign, no copy ctor</li>
  <li><tt>ios_base::Init</tt> - dtor only, no copy/assign</li>
</ul>
</blockquote>

<blockquote>
<h4>23.9.2 Class template bitset [template.bitset]</h4>
<blockquote><pre>
namespace std {
  template&lt;size_t N&gt; class bitset {
  public:
    <i>// bit reference:</i>
    class reference {
      friend class bitset;
      reference() noexcept;
    public:
      <ins>reference(const reference&amp;) = default;</ins>
      ~reference() <del>noexcept</del>;
      reference&amp; operator=(bool x) noexcept;             <i>// for</i> b[i] = x;
      reference&amp; operator=(const reference&amp;) noexcept;   <i>// for</i> b[i] = b[j];
      bool operator~() const noexcept;                   <i>// flips the bit</i>
      operator bool() const noexcept;                    <i>// for</i> x = b[i];
      reference&amp; flip() noexcept;                        <i>// for</i> b[i].flip();
    };

    <i>// 23.9.2.1, constructors</i>
    ...
};
</pre></blockquote>

<blockquote class="note">
Standard library destructors are implicitly <tt>noexcept</tt>, so it is
actually confusing to make it explicit here and nowhere else.  Removed as a
drive-by fix.
</blockquote>


<h4>23.10.9 The default allocator [default.allocator]</h4>
<blockquote><pre>
namespace std {
  template &lt;class T&gt; class allocator {
  public:
    using value_type      = T;
    using is_always_equal = true_type;
    using propagate_on_container_move_assignment = true_type;

    allocator() noexcept;
    allocator(const allocator&amp;) noexcept;
    template <class U> allocator(const allocator&lt;U&gt;&amp;) noexcept;
    ~allocator();
    <ins>allocator&amp; operator=(const allocator&amp;) noexcept = default;</ins>

    T* allocate(size_t n);
    void deallocate(T* p, size_t n);
  };
}
</pre></blockquote>


<h4>23.12.2 Class memory_resource [mem.res.class]</h4>
<blockquote><pre>
namespace std {
  class memory_resource {
    static constexpr size_t max_align = alignof(max_align_t); <i>// exposition only</i>

  public:
    <ins>memory_resource(const memory_resource&amp;) = default;</ins>
    virtual ~memory_resource();

    <ins>memory_resource&amp;	 operator=(const memory_resource&amp;) = default;</ins>

    void* allocate(size_t bytes, size_t alignment = max_align);
    void deallocate(void* p, size_t bytes, size_t alignment = max_align);

    bool is_equal(const memory_resource&amp; other) const noexcept;

  private:
    virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
    virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;

    virtual bool do_is_equal(const memory_resource&amp; other) const noexcept = 0;
  };
}
</pre></blockquote>

<blockquote class="note">
Although copy operations are defaulted here for compatibility with
the implicit declarations of C++17, it would be consistent with
the original design to actually delete them, and provide a protected
default constructor.  All the derived implementations in the standard
library delete both copy constructor and copy-assignment, and in doing
so, inhibit the move operations too.
</blockquote>


<h4>26.3.12 Class <tt>vector&lt;bool&gt;</tt></h4>
<blockquote><pre>
namespace std {
  template &lt;class Allocator&gt;
  class vector&lt;bool, Allocator&gt; {
  public:
    <i>// types:</i>
    ...

    <i>// bit reference:</i>
    class reference {
      friend class vector;
      reference() noexcept;

    <i>public:</i>
      <ins>reference(const reference&amp;) = default;</ins>
      ~reference();
      operator bool() const noexcept;
      reference&amp; operator=(const bool x) noexcept;
      reference&amp; operator=(const reference&amp; x) noexcept;
      void flip() noexcept; // flips the bit
    };

    <i>// construct/copy/destroy:</i>
    ...
  };
}
</pre></blockquote>

<h4>27.6.1 Class template istream_iterator [istream.iterator]</h4>
<blockquote><pre>
namespace std {
  template &lt;class T, class charT = char, class traits = char_traits&lt;charT&gt;,
      class Distance = ptrdiff_t&gt;
  class istream_iterator {
  public:
    using iterator_category = input_iterator_tag;
    using value_type        = T;
    using difference_type   = Distance;
    using pointer           = const T*;
    using reference         = const T&amp;;
    using char_type         = charT;
    using traits_type       = traits;
    using istream_type      = basic_istream&lt;charT,traits&gt;;

    constexpr istream_iterator();
    istream_iterator(istream_type&amp; s);
    istream_iterator(const istream_iterator&amp; x) = default;
    ~istream_iterator() = default;

    <ins>istream_iterator&amp; (istream_type&amp; s); = default;</ins>
    const T&amp; operator*() const;
    const T* operator-&gt;() const;
    istream_iterator&amp; operator++();
    istream_iterator  operator++(int);
  private:
    basic_istream&lt;charT,traits&gt;* in_stream; <i>// exposition only</i>
    T value;                                <i>// exposition only</i>
  };
}
</pre></blockquote>


<h4>27.6.2 Class template ostream_iterator [ostream.iterator]</h4>
<blockquote><pre>
namespace std {
  template &lt;class charT = char, class traits = char_traits&lt;charT&gt;&gt;
  class ostream_iterator {
  public:
    using iterator_category = ouput_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using char_type         = charT;
    using traits_type       = traits;
    using ostream_type      = basic_istream&lt;charT,traits&gt;;

    ostream_iterator(ostream_type&amp; s);
    ostream_iterator(ostream_type&amp; s, const charT* delimiter);
    ostream_iterator(const ostream_iterator&amp; x);
    ~ostream_iterator();

    <ins>ostream_iterator&amp; operator=(const ostream_iterator&amp; x);</ins>
    ostream_iterator&amp; operator=(const T&amp; value);
    ostream_iterator&amp; operator*();
    ostream_iterator&amp; operator++();
    ostream_iterator&amp; operator++(int);
  private:
    basic_ostream&lt;charT,traits&gt;* out_stream;  <i>// exposition only</i>
    const charT* delim;                       <i>// exposition only</i>
  };
}
</pre></blockquote>


<h4>27.6.3 Class template istreambuf_iterator 	[istreambuf.iterator]</h4>
<blockquote><pre>
namespace std {
  template &lt;class T, class charT = char, class traits = char_traits&lt;charT&gt;&gt;
  class ostream_iterator {
  public:
    using iterator_category = ouput_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using char_type         = charT;
    using traits_type       = traits;
    using ostream_type      = basic_istream&lt;charT,traits&gt;;

    class proxy;                          <i>// exposition only</i>

    constexpr istreambuf_iterator() noexcept;
    istreambuf_iterator(const istreambuf_iterator&amp;) noexcept = default;
    ~istreambuf_iterator() = default;
    istreambuf_iterator(istream_type&amp; s) noexcept;
    istreambuf_iterator(streambuf_type* s) noexcept;
    istreambuf_iterator(const proxy&amp; p) noexcept;

    <ins>istreambuf_iterator&amp; operator=(const istreambuf_iterator&amp;) noexcept = default;</ins>
    charT operator*() const;
    pointer operator-&gt;() const;
    istreambuf_iterator&amp; operator++();
    proxy operator++(int);
    bool equal(const istreambuf_iterator&amp; b) const;
  private:
    streambuf_type* sbuf_;               <i>// exposition only</i>
  };
}
</pre></blockquote>


<h4>29.5.3 complex specializations [complex.special]</h4>
<blockquote><pre>
namespace std {
  template&lt;&gt; class complex&lt;float&gt; {
  public:
    using value_type = float;

    <ins>complex(const complex&amp;) = default;</ins>
    constexpr complex(float re = 0.0f, float im = 0.0f);
    constexpr explicit complex(const complex&lt;double&gt;&amp;);
    constexpr explicit complex(const complex&lt;long double&gt;&amp;);

    constexpr float real() const;
    void real(float);
    constexpr float imag() const;
    void imag(float);

    complex&lt;float&gt;&amp; operator= (float);
    complex&lt;float&gt;&amp; operator+=(float);
    complex&lt;float&gt;&amp; operator-=(float);
    complex&lt;float&gt;&amp; operator*=(float);
    complex&lt;float&gt;&amp; operator/=(float);

    complex&lt;float&gt;&amp; operator=(const complex&lt;float&gt;&amp;);
    template&lt;class X&gt; complex&lt;float&gt;&amp; operator= (const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;float&gt;&amp; operator+=(const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;float&gt;&amp; operator-=(const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;float&gt;&amp; operator*=(const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;float&gt;&amp; operator/=(const complex&lt;X&gt;&amp;);
  };

  template&lt;&gt; class complex&lt;double&gt; {
  public:
    using value_type = double;

    <ins>complex(const complex&amp;) = default;</ins>
    constexpr complex(double re = 0.0, double im = 0.0);
    constexpr complex(const complex&lt;float&gt;&amp;);
    constexpr explicit complex(const complex&lt;long double&gt;&amp;);

    constexpr double real() const;
    void real(double);
    constexpr double imag() const;
    void imag(double);

    complex&lt;double&gt;&amp; operator= (double);
    complex&lt;double&gt;&amp; operator+=(double);
    complex&lt;double&gt;&amp; operator-=(double);
    complex&lt;double&gt;&amp; operator*=(double);
    complex&lt;double&gt;&amp; operator/=(double);

    complex&lt;double&gt;&amp; operator=(const complex&lt;double&gt;&amp;);
    template&lt;class X&gt; complex&lt;double&gt;&amp; operator= (const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;double&gt;&amp; operator+=(const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;double&gt;&amp; operator-=(const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;double&gt;&amp; operator*=(const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;double&gt;&amp; operator/=(const complex&lt;X&gt;&amp;);
  };

  template&lt;&gt; class complex&lt;long double&gt; {
  public:
    using value_type = long double;

    <ins>complex(const complex&amp;) = default;</ins>
    constexpr complex(long double re = 0.0L, long double im = 0.0L);
    constexpr complex(const complex&lt;float&gt;&amp;);
    constexpr complex(const complex&lt;double&gt;&amp;);

    constexpr long double real() const;
    void real(long double);
    constexpr long double imag() const;
    void imag(long double);

    complex&lt;long double&gt;&amp; operator=(const complex&lt;long double&gt;&amp;);
    complex&lt;long double&gt;&amp; operator= (long double);
    complex&lt;long double&gt;&amp; operator+=(long double);
    complex&lt;long double&gt;&amp; operator-=(long double);
    complex&lt;long double&gt;&amp; operator*=(long double);
    complex&lt;long double&gt;&amp; operator/=(long double);
    
    template&lt;class X&gt; complex&lt;long double&gt;&amp; operator= (const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;long double&gt;&amp; operator+=(const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;long double&gt;&amp; operator-=(const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;long double&gt;&amp; operator*=(const complex&lt;X&gt;&amp;);
    template&lt;class X&gt; complex&lt;long double&gt;&amp; operator/=(const complex&lt;X&gt;&amp;);
  }; 
}
</pre></blockquote>


<h4>30.5.3.1.6 Class ios_base::Init [ios::Init]</h4>
<blockquote><pre>
namespace std {
  class ios_base::Init {
  public:
    Init();
    <ins>Init(const Init&amp;) = default;</ins>
    ~Init();

    <ins>Init&amp; operator=(const Init&amp;) = default;</ins>
  private:
    static int init_cnt; <i>// exposition only</i>
  };
}
</pre></blockquote>

<blockquote class="note">
In this case, implicitly deleting the copy operations may well
be the right answer, although we propose the current edit as
no change of existing semantics.
</blockquote>

</blockquote>

<h2><a name="6.0">6 Acknowledements</h2>
<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/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/2014/n4190">N4190</a> Removing <tt>auto_ptr</tt>, <tt>random_shuffle()</tt>, And Old <tt>&lt;functional&gt;</tt> Stuff, Stephan T. Lavavej</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4259">N4259</a> Wording for std::uncaught_exceptions, Herb Sutter</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0001r1">P0001R1</a> Remove Deprecated Use of the <tt>register</tt> Keyword, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0002r0">P0002R1</a> Remove Deprecated <tt>operator++(bool)</tt>, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0003r5">P0003R5</a> Remove Deprecated Exception Specifications from C++17, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0004r0">P0004R1</a> Remove Deprecated iostreams aliases, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0005r4">P0005R4</a> Adopt 'not_fn' from Library Fundamentals 2 for C++17, Alisdair Meredith, Stephan T. Lavavej, Tomasz Kamiński</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/2016/p0521r0">P0521R0</a> Proposed Resolution for CA 14 (shared_ptr use_count/unique), Stephan T. Lavavej</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>
</ul>

</body>
</html>
