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.

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.

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.

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.

The library experience has been mixed, with no desire to remove
anything without a period of deprecation (other than gets)
and no precedent prior to C++17 for actually removing deprecated
features.

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, 20.5.4.3.1 [zombie.names]
allows vendors to continue shipping features long after they have left
the standard, as long as their existing customers rely on them.

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.

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.

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.

Redundant constexpr declarations are a relatively recent feature
of modern C++, as the constexpr 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.

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 constexpr 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.

Strong recommendation:
take no action yet, consider again for C++23.

Weak recommendation:
remove this facility from C++20.

Toronto Review: Accept strong recommendation, take no action yet.
We will consider again for C++23.

It seems early to be making this change, and it was not clear that it would
improve teachability of this corner of the language. There was a suggestion
that with a little more experience, we might also consider undeprecation for
C++23

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.

Strong recommendation:
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.

Weak recommendation:
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.

Toronto Review: Accept weak recommendation, take no action yet.
We will consider again for C++23.

There is little data yet on how much code this would break, but few
implementations provide warnings, and vendors suggest they have no
interest in adding warnings for this deprecation, as they would be
"too noisy".

It seems plausible that the linkage of the copy operations would be
less disruptive than linking the destructor to the copy operations,
and some future progress might be made in that direction, if enough
interest remains. We might also consider undeprecation in a future
standard. It seems a paper with real analysis of impact is needed
to make progress in either direction (undeprecation or removal).

Audit standard for examples like 10.1.7.2 [dcl.type.simple]p5 that rely on
implicit copies that will now be deleted.

The deprecated exception specification throw() 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.

Strong recommendation:
take no action now, and plan to remove this feature in C++23.

Weak recommendation:
remove the final traces of the deprecated exception specification syntax:

There is a preference to remove noise that adds little value to the
standard, as long as vendors are free to continue supporting a
"conforming extension" and manage actual removal (outside
of strict conformance modes) at their own leisure.

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.

There is a preference to remove noise that adds little value to the standard,
as long as vendors are free to continue supporting a "conforming
extension" and manage actual removal (outside of strict conformance modes)
at their own leisure.

Specific concerns were raised around the <ciso646> header as
some implementations are using it as the samllest header to inject version
information into their standard library. However, any such usage is a
non-standard extension, and ongoing vwendor support is easily covered under the
zombie names clause. Finally, the adoption of the <version>
header at Jacksonville, 2018 resolved most of the remaining concerns.

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.

One possibility to be more aggressive here, following the decision
to not adopt all 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.

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.

strong recommendation:
Undeprecate the remaining [depr.c.headers] and move it directly into
20.5.5.2 [res.on.headers].

Weak recommendation:
In addition to tbe above, also remove the corresponding C headers from the
C++ standard, much as we have no corresponding <stdatomic.h>,
<stdnoreturn.h>, or <threads.h>, headers.

Toronto Review: No recommendation, take no action without a
more detailed paper.

It will be difficult to reach a consensus to take any action here.
Some folks want to remove the dependency on C entirely, and remove
these headers from the C++ Standard. Another group agree with the
strong recommendation that these headers really cannot be removed
from a real implementation, so should be recognized and maintained
as a regular non-deprecated feature. There was no consensus for
the smaller matter of removing the vacuuous C headers, as the
#include itself is seen as part of the compatibility layer.
However, there was insufficient enthusiasm to push through the C11
vacuous headers that were deliberately not adopted for C++17 either.

Related to a future paper on this topic, Walter Brown has a paper,
P0657R0,
that addresses a stronger deprecation on the use of the global
namespace by the C (and by implication, C++) headers.

The char* 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. However, it is
looking increasingly likely that any future replacement facility will be
part of the std2 library initiative, providing a wholesale
replacement for the current iostreams facility. If we believe that the
future replacement is more likely to come from this direction, it would
be better to integrate this facility back into the main standard, as it
would clearly not be due a replacement within namespace std at
that point.

Strong recommendation:
take no action.

Weak recommendation:
Undeprecate the char* streams.

Toronto Review: Accept strong recommendation, take no action for C++20.

It seems that there will be papers addressing the required replacement facility
within the C++20 timeframe. We will revisit this topic again for C++23.

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.

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.

Strong recommendation:
take no action yet, unless this is our once-in-a-decade opportunity to
break ABIs.

Weak recommendation:
remove the function, and add a new entry to the [zombie.names] clause.

Toronto Review: Accept weak recommendation, strike from C++20.

There is a preference for removing replaced facilities from the standard
at the earliest opportunity, and letting the vendors remove the zombie
implementations at a time of their own choosing, assessing their own
customer demand.

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, std::not_fn,
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.

There are several superior alternatives available to the classic adaptable
function APIs. std::bind 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.

Strong recommendation:
remove this facility from C++20.

Weak recommendation:
Remove only the negators from C++20.

Toronto Review: Accept strong recommendation, strike from C++20.

There is a preference for removing replaced facilities from the standard
at the earliest opportunity, and letting the vendors remove the zombie
implementations at a time of their own choosing, assessing their own
customer demand.

One surprising issue turned up with an implementation that eagerly removed
the deprecated names. It turns out that there are platforms where size_t
and ptrdiff_t are not signed/unsigned variations on the same underlying
type, so relying on the default type computation through allocator_traits
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 allocator_traits 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.

allocator<void> 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.

Strong recommendation: Undeprecate std::allocator<T>::size_type
and std::allocator<T>::difference_type, and remove the remaining
deprecated parts from the C++20 standard:

There is a preference for removing replaced facilities from the standard
at the earliest opportunity, and letting the vendors remove the zombie
implementations at a time of their own choosing, assessing their own
customer demand.

Note that there has been additional discussion on the LWG reflector since
this paper was reviewed in LEWG that std::allocator<void>
is an important type in the Networking TS, where it is the classic model
of a proto-allocator. Removing the explicit specialization, per
the proposed resolution below, should no impact on that, as the primary
template will now provide the correct behavior. The main concern is that
the allocate and deallocate function signatures will be
present and detectable via SFINAE, but will not instantiate if called.
In particular, this would affect explict template instantiations, rather
than the typical implicit template instantiation. Note that this class
is no different to other allocators such as scoped_allocator_adaptor
and polymorphic_allocator in this regard, and it is suggested
that a separate paper on proto-allocators be written if we want to better
constrain allocators so that the allocate and deallocate
functions are not present (in general) for instantations for void.

raw_storage_iterator 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.

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

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

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.

Strong recommendation:
remove the deprecated iterator from C++20.

Weak recommendation:
take no action.

Toronto Review: Accept strong recommendation, strike from C++20.

There is a preference for removing replaced facilities from the standard
at the earliest opportunity, and letting the vendors remove the zombie
implementations at a time of their own choosing, assessing their own
customer demand.

There was some concern that the iterator may still be safely used in
special circumstances, where the user knowa that the copy constructor
will not throw, and that allocators are not involved (requiring a call
to construt). However, users able to reason that they can
safely use the iterator are also (generally) capable of providing their
own solution, and we prefer to remove a potentially dangerous tool from
the standard.

Weak recommendation:
add sufficient facilities for safe use that the facility can be undeprecated.
Details are deferred to a follow-up paper, if desired.

Toronto Review: Accept strong recommendation, strike from C++20.

There is a preference for removing replaced facilities from the standard
at the earliest opportunity, and letting the vendors remove the zombie
implementations at a time of their own choosing, assessing their own
customer demand.

It is worth noting that the domain itself is not dead, as SG 12
continues to work in this space. However, this C++98 API still
offers more than it actually provides, behind an API requiring
the user to provide their own resource wrappers, so removing this
feature gives SG 12 the most freedom to pursue a correct solution
in the future.

There is a preference for removing replaced facilities from the standard
at the earliest opportunity, and letting the vendors remove the zombie
implementations at a time of their own choosing, assessing their own
customer demand.

It is not clear that there is interest in pursuing the idea that
the iterator traits themselves default more of the typedef-names,
which is the main service the deprecated facility provides. The
whole issue may become moot with the addition of concepts and
ranges to the library, but it is too early to speculate on their
impact here.

There is a preference for removing replaced facilities from the standard
at the earliest opportunity, and letting the vendors remove the zombie
implementations at a time of their own choosing, assessing their own
customer demand.

There was a consensus to remove, that ia held back by a dependency in D.16 [depr.conversions].
There was no consesnus ro remove the latter without at least a paper showing
how users should solve their text conversion problems without these facilities.

Strong recommendation:
Remove this facility from the standard at the earliest opportunity.

Weak recommendation:
take no action yet.

Toronto Review: Take no action.

There was no consesnus ro remove this facility without at least a paper showing
how users should solve their text conversion problems without these facilities.
There was a clear desire to see such a paper in order to proceed with removing
these poorly specified features.

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.

Do Nothing

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.

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.

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.

Undeprecate

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.

This may be a consideration for long-term deprecated features that
don't appear to be going anywhere, such as the strstream
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.

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.

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.

This section integrates the proposed wording of the above
recommendations as the various working groups approve them
for review by the Core and Library Working Groups. It
immediately adopts the proposed Library Fixes for Deprecated
Features, with the expectation that libary will want to
review one integrated set of words when this paper reaches
that group.

18.4 Exception specifications [except.spec]

The predicate indicating whether a function cannot exit via an exception is
called the exception specification of the function. If the predicate is false,
the function has a potentially-throwing exception specification, otherwise it
has a non-throwing exception specification. The exception specification is
either defined implicitly, or defined explicitly by using a noexcept-specifier
as a suffix of a function declarator (11.3.5).

In a noexcept-specifier, the constant-expression, if supplied,
shall be a contextually converted constant expression of type bool
(8.6); that constant expression is the exception specification of the function
type in which the noexcept-specifier appears. A ( token that follows
noexcept is part of the noexcept-specifier and does not
commence an initializer (11.6). The noexcept-specifiernoexcept
without a constant-expression is equivalent to the noexcept-specifiernoexcept(true). The noexcept-specifierthrow() is
deprecated (D.3), and equivalent to the noexcept-specifiernoexcept(true).

Furthermore, if A::~A() 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. — end example ]

20.5.1.2 Headers [headers]

Table 17 — C++ headers for C library facilities

<cassert>

<cinttypes>

<csignal>

<cstdio>

<cwchar>

<ccomplex>

<ciso646>

<cstdalign>

<cstdlib>

<cwctype>

<cctype>

<climits>

<cstdarg>

<cstring>

<cerrno>

<clocale>

<cstdbool>

<ctgmath>

<cfenv>

<cmath>

<cstddef>

<ctime>

<cfloat>

<csetjmp>

<cstdint>

<cuchar>

Footnote 174) In particular, including the standard header
<iso646.h>or <ciso646> has no effect.

20.5.1.3 Freestanding implementations [compliance]

Table 19 — C++ headers for freestanding implementations

subclause

header

<ciso646>

21.2

Types

<cstddef>

21.3

Implementation properties

<cfloat><limits><climits>

21.4

Integer types

<cstdint>

21.5

Start and termination

<cstdlib>

21.6

Dynamic memory management

<new>

21.7

Type identification

<typeinfo>

21.8

Exception handling

<exception>

21.9

Initializer lists

<initializer_list>

21.10

Other runtime support

<cstdarg>

23.15

Type traits

<type_traits>

Clause 32

Atomics

<atomic>

D.4.2, D.4.3

Deprecated headers

<cstdalign><cstdbool>

20.5.4.3.1 Zombie names [zombie.names]

In namespace std, the following names are reserved for previous
standardization:

— auto_ptr,

— auto_ptr_ref,

— binary_function,

— binary_negate,

— bind1st,

— bind2nd,

— binder1st,

— binder2nd,

— const_mem_fun1_ref_t,

— const_mem_fun1_t,

— const_mem_fun_ref_t,

— const_mem_fun_t,

— get_temporary_buffer,

— get_unexpected,

— gets,

— is_literal_type,

— is_literal_type_v,

— mem_fun1_ref_t,

— mem_fun1_t,

— mem_fun_ref_t,

— mem_fun_ref,

— mem_fun_t,

— mem_fun,

— not1,

— not2,

— pointer_to_binary_function,

— pointer_to_unary_function,

— ptr_fun,

— random_shuffle,

— raw_storage_iterator,

— result_of,

— result_of_t,

— return_temporary_buffer,

— set_unexpected,

— unary_function,

— unary_negate,

— uncaught_exception,

— unexpected, and

— unexpected_handler.

The following names are reserved as member types for previous standardization,
and may not be used as a name for object-like macros in portable code:

— argument_type,

— first_argument_type,

— io_state,

— open_mode,

— second_argument_type, and

— seek_dir.

The name stossc is reserved as a member function for previous
standardization, and may not be used as a name for function-like macros in
portable code.

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.

30.5.3.1.6 Class ios_base::Init [ios::Init]

In this case, deleting, rather than defaulting, the copy operations may well be
the right answer, although we propose the current edit as no change of existing
semantics.

C.2.8 Clause 20: library introduction [diff.cpp03.library]

2 Affected subclause: 20.5.1.2

Change: New headers.

Rationale: New functionality.

Effect on original feature: The following C++ headers are new:
<array>,
<atomic>,
<chrono>,
<codecvt>,
<condition_variable>,
<forward_list>,
<future>,
<initializer_list>,
<mutex>,
<random>,
<ratio>,
<regex>,
<scoped_allocator>,
<system_error>,
<thread>,
<tuple>,
<typeindex>,
<type_traits>,
<unordered_map>, and
<unordered_set>.
In addition the following C compatibility headers are new:
<ccomplex>,<cfenv>,
<cinttypes>,
<cstdalign>,<cstdbool>,<cstdint>,
<ctgmath>, and
<cuchar>.
Valid C++ 2003 code that #includes headers with these names may be invalid in this International Standard.

C.5.5 Clause 18: exception handling [diff.cpp17.except]

Affected subclause: 18.4

Change: Remove throw() exception specification.

Rationale: The empty dynamic exception specification was
retained for one additional C++ Standard to ease the transition
away from this feature.

Effect on original feature: A valid C++ 2017 function declaration,
member function declaration, function pointer declaration, or function
reference declaration that uses throw() for its exception
specification will be rejected as ill-formed in this International Standard.
It should simply be replaced with noexcept for no change of meaning
since C++ 2017.

C.5.56 Clause 20: Library introduction [diff.cpp17.library]

Affected subclause: 20.5.1.2

Change: New headers.

Rationale: New functionality.

Effect on original feature: The following C++ headers are new:
<compare>, <span>, <syncstream>, and <version>.
Valid C++ 2017 code that #includes headers with these names may be invalid in this International Standard.

Affected subclause: 20.5.1.2

Change: Remove vacuous C++ header files.

Rationale: The empty headers implied a false requirement to
achieve C compatibility with the C++ headers.

Effect on original feature: A valid C++ 2017 program that
includes any of the following headers may fail to compile:
<ccomplex>, <ciso646>,
<cstdalign>, <cstdbool>, and
<ctgmath>. The #include directives can
simply be removed with no loss of meaning.

C.5.7 Annex D: compatibility features [diff.cpp17.depr]

Affected subclause: D.7

Change: Remove uncaught_exception.

Rationale: The function did not have a clear specification
when multiple exceptions were active, so has been superseded by
uncaught_exceptions.

Effect on original feature: A valid C++ 2017 program that calls
std::uncaught_exception may fail compile. It might be revised to use
std::uncaught_exceptions instead, for clear and portable semantics.

Affected subclause: D.8

Change: Remove support for adaptable function API.

Rationale: The deprecated support relied on a limited convention that could
not be extended to support the general case or new language features. It has been
superseded by direct language support with decltype, and by the
std::bind and std::not_fn function templates.

Effect on original feature: A valid C++ 2017 program that relies on the presence
of result_type, argument_type, first_argument_type, or
second_argument_type in a standard library class might no longer compile.
A valid C++ 2017 program that calls not1 or not2, or uses the class
templates unary_negate or binary_negate, may fail to compile.

Affected subclause: D.9

Change: Remove redundant members from std::allocator.

Rationale:std::allocator was overspecified, encouraging direct
usage in user containers rather than relying on std::allocator_traits,
leading to poor containers.

Effect on original feature: A valid C++ 2017 program that directly makes use
of the pointer, const_pointer, reference,
const_reference, rebind, address, construct,
destroy, or max_size members of std::allocator, or that
directly calls allocate with an additional hint argument, may fail to compile.

Affected subclause: D.10

Change: Remove raw_memory_iterator.

Rationale: The iterator encouraged use of algorithms that
might throw exceptions, but did not return the number of elements
successfully constructed that might need to be destroyed in order
to avoid leaks.

Effect on original feature: A valid C++ 2017 program that uses
this iterator class may fail to compile.

Affected subclause: D.11

Change: Remove temporary buffers API.

Rationale: The temporary buffer facility was intended to
provide an efficient optimization for small memory requests, but
there is little evidence this was achieved in practice, while
requiring the user to provide their own exception-safe wrappers
to guard use of the facility in many cases.

Effect on original feature: A valid C++ 2017 program that
calls get_temporary_buffer or return_temporary_buffer
may fail to compile.

Affected subclause: D.12

Change: Remove deprecated type traits.

Rationale: The traits had unreliable or awkward interfaces.
The is_literal_type trait provided no way to detect which
subset of constructors and member functions of a type were declared
constexpr. The result_of trait had a surprising
syntax that could not report the result of a regular function type.
It has been superseded by the invoke_result trait.

Effect on original feature: A valid C++ 2017 program that relies
on the is_literal_type or result_of type traits, on
the is_literal_type_v variable template, or on the
result_of_t alias template may fail to compile.

Affected subclause: D.14

Change: Remove shared_ptr::unique.

Rationale: The result of a call to this member function is
not reliable in the presence of multiple threads and weak pointers.
The member function use_count is similarly unreliable, but
has a clearer contract in such cases, and remains available for well
defined use in single-threaded cases.

Effect on original feature: A valid C++ 2017 program that calls
unique on a shared_ptr object may fail to compile.

C.6.1 Modifications to headers [diff.mods.to.headers]

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++.

There are no C++ headers for the C headers <stdatomic.h>,
<stdnoreturn.h>, and <threads.h>, nor are the C headers
themselves part of C++.

The headers <ccomplex> (D.4.1) and <ctgmath>
(D.4.4), as well as their corresponding C headers <complex.h>
and <tgmath.h>, do not contain any of the content from the C
standard library and instead merely include other headers from the C++ standard library.

The headers <ciso646>, <cstdalign> (D.4.2), and
<cstdbool> (D.4.3) are meaningless in C++. Use of the C++ headers
<ccomplex>, <cstdalign>, <cstdbool>, and
<ctgmath> is deprecated (D.5).

C.6.2.4 Header <iso646.h> [diff.header.iso646.h]

The tokens and, and_eq, bitand, bitor, compl,
not_eq, not, or, or_eq, xor, and xor_eq
are keywords in this International Standard (5.11).
They do not appear as macro names defined in <ciso646>.

C.6.2.5 Header <stdalign.h> [diff.header.stdalign.h]

The token alignas is a keyword in this International Standard (5.11).
It does not appear as a macro name defined in <cstdalign> (D.4.2).

C.6.2.6 Header <stdbool.h> [diff.header.stdbool.h]

The tokens bool, true, and false are keywords in this International Standard (5.11).
They do not appear as macro names defined in <cstdbool> (D.4.3).

D.3 Deprecated exception specifications [depr.except.spec]

The noexcept-specifierthrow() is deprecated.

D.4 C++ standard library headers [depr.cpp.headers]

For compatibility with prior C++ International Standards, the C++ standard
library provides headers <ccomplex> (D.4.1), <cstdalign> (D.4.2), <cstdbool>
(D.4.3), and <ctgmath> (D.4.4). The use of these headers is deprecated.

D.4.1 Header <ccomplex> synopsis [depr.ccomplex.syn]

#include <complex>

The header <ccomplex> behaves as if it simply includes the header <complex> (29.5.1).

D.4.2 Header <cstdalign> synopsis [depr.cstdalign.syn]

#define __alignas_is_defined 1

The contents of the header <cstdalign> are the same as the C standard library
header <stdalign.h>, with the following changes: The header and the
header <stdalign.h> shall not define a macro named alignas.
See also: ISO C 7.15.

D.4.3 Header <cstdbool> synopsis [depr.cstdbool.syn]

#define __bool_true_false_are_defined 1

1 The contents of the header <cstdbool> are the same as the C standard
library header <stdbool.h>, with the following changes: The header
<cstdbool> and the header <stdbool.h> shall not define macros named bool,
true, or false.
See also: ISO C 7.18.

D.4.4 Header <ctgmath> synopsis [depr.ctgmath.syn]

#include <complex>#include <cmath>

The header <ctgmath> simply includes the headers <complex> (29.5.1) and <cmath> (29.9.1).

[ Note: The overloads provided in C by type-generic macros are already
provided in <complex> and <cmath> by "sufficient" additional overloads. — end note ]

D.5 C standard library headers [depr.c.headers]

The header <complex.h> behaves as if it simply includes the
header <ccomplex>(29.5.1). The header
<tgmath.h> behaves as if it simply includes the
headers<ctgmath><complex> (29.5.1) and
<cmath> (29.9.1).

D.8 uncaught_exception [depr.uncaught]

The header <exception> has the following addition:

namespace std {bool uncaught_exception() noexcept;}

bool uncaught_exception() noexcept;

Returns:uncaught_exceptions() > 0.

D.9 Old Adaptable Function Bindings [depr.func.adaptor.binding]

D.9.1 Weak Result Types [depr.weak.result_type]

A call wrapper (23.14.2) may have a weak result type. If it does, the type
of its member type result_type is based on the type T of the wrapper's
target object:

if T is a pointer to function type, result_type shall be a
synonym for the return type of T;

if T is a pointer to member function, result_type shall be a
synonym for the return type of T;

if T is a class type and the qualified-id T::result_type is
valid and denotes a type (17.9.2), then result_type shall be a synonym for
T::result_type;

otherwise result_type shall not be defined.

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 typedef-names argument_type and result_type for function
objects that take one argument and first_argument_type,
second_argument_type, and result_type for function objects
that take two arguments.

The following member names are defined in addition to names specified in Clause 23.14:

reference_wrapper<T> has a weak result type (D.9.1). If
T is a function type, result_type shall be a synonym for the
return type of T.

The template specialization reference_wrapper<T> shall define
a nested type named argument_type as a synonym for T1 only if
the type T is any of the following:

— a function type or a pointer to function type taking one argument of
type T1

— a pointer to member function R T0::f cv (where
cv represents the member function's cv-qualifiers); the
type T1 is cv T0*

— a class type where the qualified-idT::argument_type is valid
and denotes a type (17.9.2); the type T1 is T::argument_type.

The template instantiation reference_wrapper<T> shall define
two nested types named first_argument_type and
second_argument_type as synonyms for T1 and T2,
respectively, only if the type T is any of the following:

— a function type or a pointer to function type taking two arguments of
types T1 and T2

— a pointer to member function R T0::f(T2) cv (where
cv represents the member function's cv-qualifiers); the
type T1 is cv T0*

— a class type where the qualified-ids T::first_argument_type
and T::second_argument_type are both valid and both denote types
(17.9.2); the type T1 is T::first_argument_type and the type
T2 is T::second_argument_type.

All enabled specializations hash<Key> of hash (23.14.15) provide
two nested types, result_type and argument_type, which shall be
synonyms for size_t and Key, respectively.

The forwarding call wrapper g returned by a call to
bind(f, bound_args...) (23.14.11.3) shall have a weak result type (D.9.1).

The forwarding call wrapper g returned by a call to
bind<R>(f, bound_args...) (23.14.11.3) shall have a nested type
result_type defined as a synonym for R.

The simple call wrapper returned from a call to
mem_fn(pm) shall have a nested type result_type that is a
synonym for the return type of pm when pm is a pointer to
member function.

The simple call wrapper returned from a call to
mem_fn(pm) shall define two nested types named
argument_type and result_type as synonyms for
cv T* and Ret, respectively, when pm is a
pointer to member function with cv-qualifier cv and taking no
arguments, where Ret is pm's return type.

The simple call wrapper returned from a call to
mem_fn(pm) shall define three nested types named
first_argument_type, second_argument_type, and
result_type as synonyms for cv T*, T1, and
Ret, respectively, when pm is a pointer to member function
with cv-qualifier cv and taking one argument of type T1,
where Ret is pm's return type.

The following member names are defined in addition to names specified in Clause 26:

Returns: The actual address of the object referenced by x, even
in the presence of an overloaded operator&.

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

Returns: A pointer to the initial element of an array of storage of size
n * sizeof(T), aligned appropriately for objects of type T.
It is implementation-defined whether over-aligned types are supported (6.6.5).

Remark: the storage is obtained by calling
::operator new(std::size_t) (21.6.2), but it is unspecified when or
how often this function is called.

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

explicit raw_storage_iterator(OutputIterator x);

Effects: Initializes the iterator to point to the same value to which
x points.

raw_storage_iterator& operator*();

Returns:*this

raw_storage_iterator& operator=(const T& element);

Requires:T shall be CopyConstructible.

Effects: Constructs a value from element at the location to
which the iterator points.

Returns: A reference to the iterator.

raw_storage_iterator& operator=(T&& element);

Requires:T shall be MoveConstructible.

Effects: Constructs a value from std::move(element) at the
location to which the iterator points.

Returns: A reference to the iterator.

raw_storage_iterator& operator++();

Effects: Pre-increment: advances the iterator and returns a reference to
the updated iterator.

raw_storage_iterator operator++(int);

Effects: Post-increment: advances the iterator and returns the old value
of the iterator.

OutputIterator base() const;

Returns: An iterator of type OutputIterator that points to the
same value as *this points to.

Effects: Obtains a pointer to uninitialized, contiguous storage for
N adjacent objects of type T, for some non-negative number
N. It is implementation-defined whether over-aligned types are supported
(3.11).

Remarks: Calling get_temporary_buffer with a positive number
n is a non-binding request to return storage for n objects of
type T. In this case, an implementation is permitted to return instead
storage for a non-negative number N of such objects, where
N!= n (including N == 0). [ Note: The
request is non-binding to allow latitude for implementation-specific
optimizations of its memory management. - end note ]

Returns: If n <= 0 or if no storage could be obtained,
returns a pair P such that P.first is a null pointer value
and P.second == 0; otherwise returns a pair P such that
P.first refers to the address of the uninitialized storage and
P.second refers to its capacity N (in the units of
sizeof(T)).

template <class T> void return_temporary_buffer(T* p);

Effects: Deallocates the storage referenced by p.

Requires:p shall be a pointer value returned by an earlier
call to get_temporary_buffer that has not been invalidated by an
intervening call to return_temporary_buffer(T*).

is_literal_type<T> is a UnaryTypeTrait (23.15.1) with a base
characteristic of true_type if T is a literal type (6.7), and
false_type otherwise.

Requires:Fn and all types in the parameter pack ArgTypes shall be complete types, cvvoid, or arrays of unknown bound.

The partial specialization result_of<Fn(ArgTypes...)> is a
TransformationTrait (23.15.1) whose member typedef type is
defined if and only if invoke_result<Fn, ArgTypes...>::type
(23.14.4) is defined. If type is defined, it names the same type as
invoke_result_t<Fn, ArgTypes...>.

template<class T> struct is_pod;

Requires:remove_all_extents_t<T> shall be a complete type or cvvoid.

is_pod<T> is a UnaryTypeTrait (23.15.1) with a base
characteristic of true_type if T is a POD type, and
false_type otherwise. A POD class is a class that is both a trivial
class and a standard-layout class, and has no non-static data members of type
non-POD class (or array thereof). A POD type is a scalar type, a POD class, an
array of such a type, or a cv-qualified version of one of these types.

[ Note: It is unspecified whether a closure type (8.4.5.1) is a POD type.
— end note ]

D.15 Deprecated shared_ptr observers [depr.util.smartptr.shared.obs]

The following member is defined in addition to those members specified in 23.11.3: