Document #: | D2863R8 |
Date: | 2024-12-09 |
Project: | Programming Language C++ |
Audience: |
SG1, Core, LEWG |
Reply-to: |
Alisdair Meredith <ameredith1@bloomberg.net> |
*this
by reference
[depr.capture.this]volatile
types
[depr.volatile.type]static constexpr
data members
[depr.static.constexpr]template
keyword before
qualified names [depr.template.template]has_denorm
members in
numeric_limits
[depr.numeric.limits.has.denorm]char *
streams
[depr.str.strstreams]polymorphic_allocator
member
function [depr.mem.poly.allocator.mem]iterator
class template
[depr.iterator]move_iterator
access
[depr.move.iter.elem]shared_ptr
atomic access
[depr.util.smartptr.shared.atomic]basic_string
capacity
[depr.string.capacity]This paper evaluates all the deprecated facilities of the C++23 Standard and recommends removing a subset from Annex D in C++26, either by removal from the Standard entirely or by undeprecation and restoring the subset to the main text. Such recommendations will be pursued in specific papers, and this paper acts as an index into that work.
With the release of a new C++ Standard, we get an opportunity to revisit the features identified for deprecation, and consider if we are prepared to clear any out yet, either by removing completely from the standard, or by reversing the deprecation decision and restoring the feature to full service. This paper makes no attempt to offer proposals for removing features other than those deprecated in Annex D, nor does it attempt to identify new candidates for deprecation.
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 dead-weight. It should be noted that only two of the current twenty-nine deprecated feature were deprecated prior to C++17, as we have made good progress are resolving long-standing deprecations. However, the desire to support customers and not needlessly break their code makes a full clear-out impractical. This paper continues the tradition of maintaining a single paper to focus attention of efficiently reviewing the case for and against removal, or undeprecation, of each deprecated feature of the just-published standard, the meeting after that standard has been sent to ISO for the final publication ballot.
In contrast to previous years, all work to change the status of a feature, by removal or undeprecation, will be delegated to a paper on that feature. Thus, work proceeds on each feature without delaying everything to the pace of the slowest feature and the author’s ability to update this summary paper in a timely manner. Note that many reviews will still be processed by this paper, where no further action is intended on a feature for C++26.
The benefits of making the choice to remove features early in a standard cycle is that we will get the most experience we can from the bleeding-edge adopters whether a particular removal is more problematic than expected - but even this data point is limited, as bleeding-edge adopters typically have less reliance on deprecated features, eagerly adopting the newer replacement facilities.
However, do note that with the three year release cadence for the C++ Standard, we will often be re-evaluating features whose deprecated status has barely reached print.
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.
Informal feedback on library deprecation when performing these reviews for previous standards leans in two directions: deprecation is for life, and we should never remove anything, as there is no reason for the library to ever break client code; and alternatively with the addition of zombie names there is clear intent library vendors should continue supporting deprecated features as long as their customers demand them, without violating conformance, and that removal from the standard removes maintenance costs from wg21 (placed instead on library vendors) and that this paper should be aggressive in its recommendations to remove deprecated features.
We will review each deprecated facility, and make a recommendation to either remove that feature, undeprecate that feature, or take no action. A recommendation to remove or undeprecate will delegate that work to a follow-up paper, tracked by a checklist below. The author provides several papers that do just that for features where the abandoned review for C++23 had expressed a strong intent to remove. In other cases “Request Paper” is indicated, which would be the result of evolution review wanting to proceed with undeprecation or removal that the current author does not have the resources to pursue.
This table will track progress of all papers targeting features deprecated in the C++23 Standard, according to the last public draft, [N4950]. As such, the subclause references will not update if new deprecations occur during C++26, as we track only the features deprecated in the current published standard.
It notes the standard that introduced the feature; the standard and paper that deprecated that feature; the current recommendation of action to take, with a reference to the delegated paper that will propose those changes; and the current working group that has ownership of that review. Any recommendation of “No action” means the review is in this paper.
Once the review of a feature is completed, either by confirming No action or adopting a reviewed paper in plenary, the Owner will change to Done.
Subclause
|
Feature
|
Introduced
|
Deprecated
|
By Paper
|
Recommendation
|
Owner
|
---|---|---|---|---|---|---|
D.2 | Arithmetic conversion on enumerations | C++98 | C++20 | [P1120R0] | Remove: [P2864R2] | DONE |
D.3 | Implicit capture of *this by
reference |
C++11 | C++20 | [P0806R2] | No action | DONE |
D.4 | Array comparisons | C++98 | C++20 | [P1120R0] | Remove: [P2865] | WP |
D.5 | Deprecated use of
volatile |
C++98 | C++20 | [P1152R4] | Address by [P2866] | CWG |
D.6 | Redeclare static constexpr
members |
C++11 | C++17 | [P0386R2] | No action | DONE |
D.7 | Non-local use of TU-local entities | C++98 | C++20 | [P1815R2] | No action | DONE |
D.8 | Implicit special members | C++98 | C++11 | [N3203] | No action | DONE |
D.9 | Some literal operator declarations | C++11 | C++23 | [CWG2521] | No action | DONE |
D.10 | template keyword before
qualified names |
C++98 | C++23 | [P1787R6] | No action | DONE |
Subclause
|
Feature
|
Introduced
|
Deprecated
|
By Paper
|
Recommendation
|
Owner
|
---|---|---|---|---|---|---|
D.11 | Requires: clauses | C++98 | C++20 | Editorial | Remove: [P2874R1] | DONE |
D.12 | has_denorm members in
numeric_limits |
C++98 | C++23 | [P2614R2] | No action | DONE |
D.13 | Deprecated C macros | C++98 | C++23 | [P2790R0] | Defer to rebase on C23 | DONE |
D.14 | relops |
C++98 | C++20 | [P0768R1] | Remove: [P3047] | LEWG |
D.15 | char * streams |
C++98 | C++98 | N/A | Remove: [P2867R2] | DONE |
D.16 | Deprecated error numbers | C++11 | C++23 | [P2790R0] | No action | DONE |
D.17 | The default allocator | C++17 | C++23 | [LWG3170] | Remove: [P2868R3] | DONE |
D.18 | polymorphic_allocator::destroy |
C++17 | C++23 | [LWG3036] | Undeprecate: [P2875R4] | DONE |
D.19 | Deprecated type traits | C++11 | C++20 | [P0767R1] | No Action | DONE |
C++11 | C++23 | [P1413R3] | ||||
D.20 | volatile tuple API |
C++11 | C++20 | [P1831R1] | Remove: [P2866] | LWG |
D.21 | volatile variant API |
C++17 | C++20 | [P1831R1] | Remove: [P2866] | LWG |
D.22 | std::iterator |
C++98 | C++17 | [P0174R2] | Remove: [P3365] | LEWG |
D.23 | move_iterator::operator-> |
C++11 | C++20 | [P1252R2] | Defer to [P3039R0] | DONE |
D.24 | C API to use shared_ptr
atomically |
C++11 | C++20 | [P0718R2] | Remove: [P2869R4] | DONE |
D.25 | basic_string::reserve() |
C++98 | C++20 | [P0966R1] | Remove: [P2870R3] | DONE |
D.26 | <codecvt> |
C++11 | C++17 | [P0618R0] | Remove: [P2871R3] | DONE |
D.27 | wstring_convert et al. |
C++11 | C++17 | [P0618R0] | Remove: [P2872R3] | DONE |
D.28 | Deprecated locale category facets | C++11 | C++20 | [P0482R6] | Remove: [P2873] | LEWG |
D.29 | filesystem::u8path |
C++17 | C++20 | [P0482R6] | Remove: [P3364] | LEWG |
D.30 | atomic operations | C++11 | C++20 | [P0883R2] | Address by [P2866] | LWG |
Address by [P3366] | SG1 |
There is no normative content in the general clause, so nothing to do. We mention it here only so that the automatic subtitle numbering stays in sync with Annex D of [N4950].
Implicit arithmetic conversion on unscoped enumerations when involved in mixed operations with another type are part of our C heritage, but were deprecated to match up with the design of the spaceship operator for C++20 by paper [P1120R0].
A full rationale for why we should act to remove these deprecated conversions now, along with full core wording, is addressed by paper [P2864R2].
Concerns were raised about a lack of real implementation experience, especially in SFINAE contexts where deprecation warnings cannot reach. There remain some concerns about C compatibility. See [P2864R2] for details.
There will be no further progress on this topic for C++26, and we should look to present a stronger motivation and usage experience for the C++29 review.
Adopted into Working Draft N4971.
*this
by reference
[depr.capture.this]This feature was deprecated in C++20 by [P0806R2]. Its removal would potentially impact on programs written against C++11 or a later standard, when lambda captures were first introduced.
The concern addressed by the paper is that the implicit capture of
this
as a reference to data
members on a default-capture that copies is surprising and often
misleading. C++20 introduced the explicit capture of
this
as a pointer, or
*this
by value, to clearly
disambiguate the different use cases.
MSVC, gcc, and EDG front ends have been warning about this deprecation since their experimental C++20 support, before the standard itself was ratified. As of the publication of this paper, the Clang compiler still does not warn on use of this feature, although a patch to add that warning is checked into the compiler trunk for what should become Clang 17.0.
Experience over the last few years has been mixed, as several compilers would warn on the preferred syntax as redundant before C++20, so it becomes difficult to get a warning free build with a single syntax, and is typically achieved by users proving a macro to choose the preferred form.
The lack of warning in Clang suggests the may be many users of modern C++ that are still unaware of this deprecation, so the tentative recommendation is to take no action in C++26, and reconsider more carefully for C++29. However, the mixed experience of having users decide which warning they prefer suggests we might want to take more decisive action for this review, which would require a follow-up paper to consider the merits of removal vs. undeprecation.
Consensus to leave deprecated for another release cycle.
Implicit array-to-pointer decay when invoking any of the comparison operators is part of our C heritage, but these conversions were deprecated to match up with the design of the spaceship operator for C++20 by paper [P1120R0].
The implicit decay in these cases is often misleading and rarely helpful. A full rationale for why we should act to remove these deprecated conversions now, along with full core wording, is addressed by paper [P2865].
No concerns were raised, and this paper proceeds to Core.
Concerns were raised about comparison with null pointers, and this paper was sent back to EWG.
Wording updated to preserve non-deprecated semantics. Suggest creating a new paper to propose deprecation and removal of array comparison with null pointer constants.
Paper sent back to Core.
No concerns raised, although it might be useful to send a similar paper to WG14 who have not yet even deprecated these comparisons.
Approved for plenary with a few edits.
volatile
types
[depr.volatile.type]The volatile
keyword is part
of our C heritage, but a variety of usages were deprecated for C++20, in
conjunction with our C liaison, by paper [P1152R4].
As the C committee looked to adopt our deprecations, they got feedback from their vendors that they considered some of the deprecated uses as essential, so a subset of this functionality was undeprecated for C++23 by [P2327R1].
The remaining set of deprecated operations remain an often misleading source of bugs, so paper [P2866] provides further rationale for why we should act to remove these deprecated conversions now, along with full core and library wording.
Extensive discussions about volatile structured bindings, see [P2866] for details.
Ultimately, there was consensus to send this document onto its next stage, which is LEWG, and then proceeding straight to Core.
Raised concerns for EWG to confirm removal of volatile function parameters, and the design intent around the (lack of) support of assigning to volatile lvalues in unevaluated contexts.
Further concern that SG22 should review and give feedback before we would advance to a plenary poll.
Concerns shared regarding removal of volatile by-value function parameters. Sent back to EWG for further consideration.
After making the case that volatile access to by-value parameters is not observable within the C++ memory model, and that implementations that wish to support tooling responding to such qualification are free to continue doing so, as long as they emit a diagnostic for the purposes of now being a vendor extension, the paper was sent back to CWG for C++26 without changes.
Requested a few edits that were not completed in time to move to plenary. An update will be provided before the next meeting.
static constexpr
data members
[depr.static.constexpr]Static constexpr
data members
were added to the language in C++11, as part of the initial
constexpr
feature. However, they
still required a definition of the member outside the class. When inline
variables were added in C++17 by [P0386R2] then
static constexpr
data members
became implicitly inline
, and
the external definition became redundant, so was deprecated. By the time
C++26 is published, such out-of-class definitions will have been
deprecated longer than they were required.
However, as of writing this paper in March 2023, none of the 4 major compiler front ends report a deprecated use warning on the example in the standard, including the latest trunk build for open source compilers. Therefore, the tentative recommendation of this paper is for no action in the standard towards removing this feature, and encourage the front ends to start reporting deprecated usage to their users. We might consider undeprecation given the lack of enthusiasm of vendors to warn on redundant definitions, although that would feel like a step backwards, maintaining an exception to the One Definition Rule.
When considering the removal of redundant definitions, it seems simple enough to support a code base that is common with C++11 and the feature removal (or warned deprecation) with a simple feature check:
#if !defined(__cpp_inline_variables)
constexpr Type Class::Member;
#endif
There is no interest in removing a feature that does no harm, and that no compilers are yet issuing deprecation warnings for.
Then the question was whether to undeprecate this feature, as deprecation seems to have had no impact.
Poll: EWG is interested in undeprecating defining inline
constexpr
class variables
(P2863R0 section 6.6).
SF F N A SA 2 12 7 3 0
A follow-up paper is expected from the same author promoting and proposing undeprecation.
Submitted paper [P2984R0] to address this deprecation.
Presented the paper, and raised concerns that both Clang and gcc
implement a deprecation warning for this feature, but it is not enabled
when compiling with
-Wall -Wextra -pedantic
. To
enable this kind of deprecation warning you need the less well known
-Wdeprecated
command line flag,
or to know the exact name of the warning flag for this specific
deprecation. On a quick show of hands only around 1/3 of the room were
aware of this flag.
Seeking direction, we polled both to undeprecate the feature, and separately to remove it. Neither poll reached consensus and there are no plans to pursue this further for C++26. It will be revisited with all other deprecated features for C++29.
There was a desire raised for the compiler vendors to add all the
warnings controlled by
-Wdeprecated
to one of the more
widely used flags such as
-Wextra
or
-pedantic
, but that remains a
QoI concern for the vendors themselves.
Separately, we should encourage more open source projects to test build with this flag enabled.
This feature was deprecated for C++20 as part of the effort to cleanly introduce modules into the language, and was adopted by paper [P1815R2]. It potentially impacts on code written against C++98 and later standards.
This feature was deprecated only at the final meeting of the C++20 development cycle, and at the time this paper is written, deployment experience with standard modules is still limited, and it is not clear if we have any insight into how much code has been impacted by this deprecation. No current compilers issue a deprecation warning on affected code. As such, the tentative recommendation is too take no action — there is not even sufficient experience to consider undeprecation.
Consensus to leave deprecated for another release cycle.
This feature was deprecated for C++11 by paper [N3203] as part of integrating a good user experience defining classes now that rvalue references are part of the language. The deprecated parts address the default behavior of C++03 code.
The following test program will demonstrate deprecation warnings in
gcc since release 9.1, and Clang since release 10.0. For both compilers,
the command line switch -Wextra
is required to enable these deprecation warnings. As of the publication
of this paper in April 2023, the EDG and MSVC front ends do not appear
to support this warning yet.
struct A {
() = default;
A(A const&){}
A};
struct B {
& operator=(B const&){ return *this; }
B};
struct C {
~C() {}
};
int main() {
{};
A a= a;
A ax = ax; // use of deprecated operator
a
{};
B b= b; // use of deprecated constructor
B bx = bx;
b
{};
C c= c; // no-one warns on deprecated constructor
C cx = cx; // no-one warns on deprecated operator
c }
Note that no compiler is warning on copy operations in case
C
, declaring a user provided
destructor.
This topic was last considered by EWG for C++23 at the 2022 Kona meeting, where core issue 2132 looked into undeprecation. The notes on that discussion offer nothing more than an immediate call for consensus to not deprecate, and close that issue as NAD.
This is the oldest deprecated Core language facility, the only one remaining that was deprecated before C++17. When C++26 is published it will have been deprecated for 16 years so the tentative recommendation for this paper is to request authors for a paper providing a considered analysis of removal and undeprecation, in whole or in part, for C++26.
Consensus to leave deprecated for another release cycle. We would consider re-opening if someone came forward with a paper that addressed user impact in the real world, especially with SFINAE contexts that are not easily detected by deprecation warnings.
The use of whitespace between the
operator ""
and the
following identifier to denote a user-defined literal suffix was
deprecated for C++23 by Core
issue 2521. In deprecating this feature at the 2023 Issaquah
meeting, there is a clear intent that this is one step along the way to
actively remove that support:
EWG had consensus on “The form of User Defined Literals that permits a space between the quotes and the name of the literal should be deprecated, and eventually removed. Additionally, the UDL name should be excluded from the restriction in 5.10 [lex.name] in the non-deprecated form (sans space).”
Given the lateness in the process of this deprecation, no currently available compiler has a deprecation warning, nor even the trunk builds of open source compilers. Hence, the tentative recommendation is to take no action.
However, given the expressed intent to actively remove the support for that whitespace, we may want to consider how actively we want to pursue removal, and request a paper to research whether such removal would be viable in the 3 year release cycle from C++23 to C++26.
Consensus to leave deprecated for another release cycle.
template
keyword before
qualified names [depr.template.template]This feature was deprecated for C++23 by paper [P1787R6], Declarations and where to find them. The following code sample is used to test whether compilers have implemented that paper yet, and whether they diagnose the deprecated use:
template <class T> struct A {
void f(int);
template <class U> void f(U);
};
template <class T>
struct B {
template <class T2> struct C { };
};
// deprecated: T::C is assumed to name a class template:
template < class T
template <class X> class TT = T::template C
, >
struct D { };
<B<int> > db;
D
// recommended: T::C is assumed to name a class template:
template < class T
template <class X> class TT = T::C
, >
struct E { };
<B<int> > db; E
Testing with the latest compilers available from Godbolt Compiler Explorer shows that no current compiler has implemented this part of that paper yet. Without the implementation, not only are there no deprecation warnings, the recommended code transformation does not compile.
Given the current lack of implementation, it seems far too early to consider removing this feature, so the tentative recommendation is to take no action.
Given the change in C++11 to accept redundant use of the
typename
keyword in Core
issue 382 we might consider undeprecating this feature before
compilers start issuing deprecation warning.
Further, C++11 also allowed redundant use of
::template
where not required in
non-template cases, Core
issue 468, suggesting a level of redundancy is desirable so that
users are not expected to have such a precise mental compiler,
especially when learning the language.
Consensus to leave deprecated for another release cycle.
This style of documentation was deprecated editorially for C++20 following the application of a sequence of papers to update each main library clause, consistently following the new conventions established by paper [P0788R3]. The author provides a paper with tentative wording to apply the last of those changes to Annex D, [P2874R1].
Note that resolving this will touch wording in clauses D.14, D.19, D.24, D.27, and D.29. We do not track these changes in the paper index above, as they have no impact on whether deprecated library facilities are removed, although the edits would be helpful should we desire to undeprecate any of those clauses.
After applying corrections, sent [P2874R1] to poll in the Varna plenary.
Adopted into Working Draft N4958.
has_denorm
members in
numeric_limits
[depr.numeric.limits.has.denorm]This small part of
numeric_limits
for
floating-point types was deprecated for C++23 by paper [P2614R2].
As a relatively late change to the Standard Library, we have little experience in how widely triggered the deprecation warning will be, so the tentative recommendation of this paper is to take no action.
However, it is worth noting that the Zombie Names policy means that even if we were to remove this feature from the standard tomorrow, vendors can continue to maintain this feature as a conforming extension for as long as their customers demand, so with the perceived low risk it may be worth asking for a paper to remove this feature entirely from C++26.
It was observed that code searches show almost no use of these names. However, they were deprecated only within the last 12 months as part of the C++23 standard, that is still awaiting the final stages of publication.
Consensus to make no changes for C++26.
The C Standard Library headers were undeprecated for C++23 by paper [P2340R1]. Then the C macros that report that identifiers corresponding to C++ keywords have been defined as macros in language support headers were again deprecated as “immediate issues” by paper [P2790R0], resolving national body comments.
It was noted during review that these tokens will become true keywords in C23, so the pending C Standard will be removing these macros. Hence, they remain deprecated in C++23, and we except to see them removed by a paper updating the C++26 Standard to use the latest C Standard Library.
The tentative recommendation of this paper is to take no action as part of this deprecation review, anticipating the C library update paper where this change would be one small part of the larger whole.
Consensus to follow the suggestion of this paper, and handle any progress on removal as part of any future paper to rebase our standard onto C23.
The std::rel_ops
namespace
was introduced in the original C++ Standard, so its removal would
potentially impact on code written against C++98 and later standards. It
was deprecated with the introduction of support for the 3-way comparison
“spaceship” operator in C++20, by paper [P0768R1].
As of publishing this paper, none of the three popular standard libraries give any deprecation warnings on the sample code in the Tony tables below.
Deprecated
|
Modern
|
---|---|
|
|
The 2023 version of this paper erroneously claimed that all the
comparisons would be synthesized from the same two operations relied
upon by the rel_ops
operators.
In fact, those rules rely upon supplying the 3-way comparison operator,
rather than operator<
, as
illustrated above.
Note the three changes:
#include
a different
headerGiven the current lack of deprecation warnings, the tentative recommendation of this paper is to take no action for C++26 and encourage Standard Library maintainers to annotate their implementations as deprecated before the next standard cycle.
As the
using namespace std::rel_ops
idiom may be seen as encouraging bad hygiene, especially when applied at
global/namespace scope in a header, there may still be folks motivated
to write a paper expressing a stronger intent to remove this feature for
C++26.
As a historical note, the Standard Library specification itself used
to rely on std::rel_ops
to
provide the specification for any comparison operator if the necessary
wording were missing. However, as part of C++20, it was confirmed that
no current wording relies on that legacy fall-back, and the
corresponding as-if wording was removed.
char *
streams
[depr.str.strstreams]The char*
streams were
provided, pre-deprecated, in C++98 and have been considered for removal
before. All the necessary facilities to migrate to safer and easier to
use streaming facilities were added in C++20 and C++23, so the
recommendation is to remove the deprecated
char *
streams from C++26 by
[P2867R2].
Forward to POLL with 20 votes for and none against.
Poll taken: [P3053R0]
Poll results: [P3054R0]
Conclusion: Forward to LWG
Approved for plenary poll with minor edits.
Adopted into Working Draft N4981.
Several macros and enumerators for
enum class errc
were deprecated
for C++23 by [P2790R0]. While
there is no apparent urgency for their removal given how recently they
were deprecated, the zombie names clause would also give vendors
adequate coverage to retain support at their discretion. This proposal
weakly recommends retaining these names until C++29.
These names were deprecated late in the C++23 process, and that standard is still working its way through ISO publication. Consensus to make no changes here for C++26, allowing time to gain experience with the deprecation.
The Standard Library
allocator
class has a member
that can be synthesized from the primary
allocator_traits
template, and
was deprecated by [#LWG3170]. By providing this member directly, any
classes that derive from
std::allocator
will not
synthesize this value correctly, but use the
true_type
value provided
directly by std::allocator
,
forcing such allocators to provide their own override when that value
could otherwise by synthesized correctly.
While this is a small corner for misuse, the concern is embarrassing to explain, and the Standard Library allocator is a common example folks will follow when trying to write their first allocators. Hence, this paper recommends the removal of this deprecated typedef for C++26 by [P2868R3].
Discussion led to an updated paper with more rationale.
Final tally: 10 forward to POLL, no objections.
Forward to the next electronic poll to send to LWG.
Poll taken: [P2972R0]
Poll results: [P3020R0]
Conclusion: Forward to LWG
Adopted into Working Draft N4971.
polymorphic_allocator
member
function [depr.mem.poly.allocator.mem]This feature was deprecated by [#LWG3036]. However, the author of
this paper believes that
std::pmr::polymorphic_allocator
is an allocator that will be used in non-generic circumstances, unlike
std::allocator
, so this member
function that could otherwise be synthesized should still be part of its
pubic interface. Hence, the recommendation is to undeprecate with paper
[P2875R4]
Paper withdrawn until it presents more rationale.
Revised paper available in this mailing.
Approved for plenary poll with minor edits.
Adopted into Working Draft N4981.
The is_pod
trait was
deprecated for C++20 by paper [P0767R1] as part of removing the POD
vocabulary from the C++ Standard, both core and library. The term had
changed meaning so frequently that it no longer served as useful
vocabulary. The type trait was extracted to Annex D, and now itself
provides the only definition in the standard for a POD. Client code is
encouraged to use the more specific traits for trivial and standard
layout types to better describe their need. Note that the related term
POF, for Plain Old Function, was removed from C++17 by paper [P0270R3].
The is_pod
trait was first
supplied as part of C++11, so its removal would potentially impact
programs written against the C++11 Standard or later. Users have had up
to three years of implementations warning on use of the deprecated
trait, so we could consider removal, with the usual proviso that the
name is preserved as a zombie for previous standardization. As the case
for removal is not urgent, this paper recommends the removal of this
trait from the C++26 Standard, but only weakly. However, the current
wording does not follow library best practices, and should be updated to
better specify the Requires clauses with our modern vocabulary if it is
retained.
The type traits
aligned_storage
and
aligned_union
were deprecated
for C++23 by [P1413R3]. They do
use modern library wording, and as they do no active harm the
recommendation is to retain them for C++26 to allow proper time for
users to update their code, and consider again for removal in C++29.
Tested the following program to observe deprecation warnings for the
is_pod
trait through a variety
of standard library implementations at Godbolt Compiler Explorer:
#include <type_traits>
int main() {
static_assert(std::is_pod<int>::value, "oops");
static_assert(std::is_pod_v<int>, "oops");
}
Most of these type traits were deprecated only as recently as C++23, which is still wending its way through the ISO publication process. The remaining trait has been retained as the one remaining place in the standard that defines and uses the term POD. Consensus to make no changes for C++26
This library was deprecated as part of the work on deprecating unnecessary volatile facilities, so its removal is recommended by paper [P2866].
Confirmed there were no concerns, and submitted for electronic poll to forward to LWG.
Poll taken: [P3053R0]
Poll results: [P3054R0]
Conclusion: Forward to LWG
Some minor concerns with Annex C wording, but ready for plenary once Core parts are approved.
This library was deprecated as part of the work on deprecating unnecessary volatile facilities, so its removal is recommended by paper [P2866].
Confirmed there were no concerns, and submitted for electronic poll to forward to LWG.
Poll taken: [P3053R0]
Poll results: [P3054R0]
Conclusion: Forward to LWG
Some minor concerns with Annex C wording, but ready for plenary once Core parts are approved.
iterator
class template
[depr.iterator]The class template iterator
was first deprecated in C++17 by the paper [P0174R2]. The concern was that providing
the needed support for iterator typenames through a templated base
class, determining which name maps to which type purely by parameter
order, was less clear than simply providing the needed names. Further,
there were corner cases in usage that fell out of template syntax that
made this tool hard to recommend as a simpler way of providing the type
names, yet that was its whole reason to exist.
When this facility was reviewed for removal in C++20, it was noted
that there were valid uses that relied on the default template arguments
to deduce at least a few of the needed type names. Subsequent work on
iterators and ranges ([P0896R4]) that
landed in C++20 now means that work is also done by the primary
iterator_traits
template, and so
the remaining use case (for new code) is also covered, making this class
template strictly redundant.
The main concern that remains is breaking old code by removing this
code from the standard libraries. That risk is ameliorated by the zombie
names clause in the standard, allowing vendors to maintain their own
support for as long as their customers demand. By the time C++23 ships,
those customers will already have been on 6 years notice that their code
might not be supported in future standards. However, we note the
repeated use of the name
iterator
as a type within many
containers means we might choose to leave this name off the zombie list.
We conservatively place it there anyway, to ensure that we are covered
by the previous standardization terminology to encompass uses other than
as a container iterator typedef.
The recommendation of this paper is to take no action in C++26 until the is a stronger consensus for removal.
Concerns were raised about the lack of research into how much code is
likely to break with the removal of this API. We would like to see more
numbers and analysis on publicly available code, such as across all of
Github. The better treatment of implicit generation of
iterator_traits
in C++23, and
more familiarity with a limited number of code bases that still rely on
this facility, gave more confidence in moving forward with removal than
we had for C++20. It was also noted that the name may be unfortunate
with the chosen form of concept naming adopted for C++20, and so its
removal might lead to one fewer sources of future confusion. Given that
implementers are likely to provide an implementation (through zombie
names freedom) for some time after removal, there was consensus to
proceed with removal, assuming the requested research does not reveal
major concerns before the main LEWG review to follow.
move_iterator
access
[depr.move.iter.elem]This feature was deprecated for C++20 by the paper [P1252R2] highlighting the concern that
for a move iterator adapter, intending to expose its target as an rvalue
(or xvalue), the arrow operator must return the original adapted
iterator, which will likely produce an lvalue when dereferenced. This
operator is not fit for purpose, and cannot be fixed. The workaround for
users is to dereference the move iterator with
operator *
and call the member
they wish to access using the familiar
.
notation. This preserves the
value category of the iterator’s target.
The proposal for C++20 was to deprecate this operator, with a view to
removal at a later date. However,
operator->
support is part of
the Cpp17InputIterator requirements, so cannot be removed
without addressing that definition. One option might be to accept the
std::move_iterator
is
not a Cpp17InputIterator at all, but models the
input_iterator
concept instead.
That might mean deprecating the
iterator_category
typedef member
as well.
Testing the following program with Godbolt Compiler Explorer, it appears that libc++ is the only Standard Library implementation, at the time of writing this paper, that warns on use of the deprecated operator, and has done so only since Clang 15:
#include <iterator>
struct Wrap {
int data;
};
int main() {
= {42};
Wrap x ::move_iterator it = std::make_move_iterator(&x);
stdauto y = it->data;
}
The recommendation is to take no action at this time, unless a more detailed paper is requested.
It was observed that David Stone is doing work in this space with more support for implicitly generated operators, [P3039R0]. Consensus is to delegate this deprecated operator to that paper, thinking that is the appropriate direction to support removal of the deprecated function.
shared_ptr
atomic access
[depr.util.smartptr.shared.atomic]The legacy C-style atomic API for manipulating shared pointers
provided in C++11 is subtle, frequently misunderstood, and easily
misused to cause data races. A type-safe replacement facility that also
provides support for
atomic<weak_ptr<T>>
was added to C++20, so we recommend removing the legacy API at the
earliest opportunity.
See paper [P2869R4] for a more detailed discussion and proposed wording.
Polled after discussion of the header compatibility concern:
Poll: Remove deprecated
shared_ptr
atomic access APIs
from C++26, with any of the library options listed in P2689?
SF F N A SA 2 4 1 1 0
Consensus to move this paper to LEWG to resolve the header design issue, and then continue on to LWG.
A quick code search suggested the amount of code that would be broken by removal, requiring the relatively simple workaround in the paper, was non-zero but sufficiently small.
As the amount of affected code is small, there was no desire to spend any effort minimizing the burden of conversion by making existing features and functions available through more headers — so do not attempt to provide any solution for the header concerns.
Add to the next electronic poll for submitting to LWG for C++26.
Poll taken: [P3053R0]
Poll results: [P3054R0]
Conclusion: Forward to LWG
Approved for plenary poll with minor edits.
Adopted into Working Draft N4981.
basic_string
capacity
[depr.string.capacity]See paper [P2870R3] for a more detailed discussion and proposed wording to remove this facility from C++26.
There was one objection that was withdrawn when it was realized that the C++03 behavior became a no-operation in C++11, so finally removing that overload helps users find remaining code that needs updating to use the C++11 name to preserve behavior.
Final tally: 18 forward to POLL, no objections.
Forward to the next electronic poll to send to LWG.
Poll taken: [P2972R0]
Poll results: [P3020R0]
Conclusion: Forward to LWG
Adopted into Working Draft N4971.
This feature was originally proposed for C++11 by paper [N2007] and deprecated for C++17 by paper [P0618R0]. As noted at the time, the feature was underspecified, a source of security issues handling malformed Unicode, and would require more work than we wished to invest to bring it up to standard. Since then SG16 has been convened and is producing a steady stream of work to bring reliable well-specified Unicode support to C++.
Given vendors propensity to provide ongoing support for deprecated libraries under the zombie name reservations, we recommend removal from C++26, see paper [P2871R3] for details.
There were some concerns about removal before an alternative solution lands. However, it was then pointed out that the names in this API lie as they refer to UTF-16 but actually implement UCS-2, and so must provide a definition for UCS-2 as it is no longer defined in the Unicode standard.
No objections to removal in C++26.
Several folks who did not object were still concerned that we would be removing a facility before a replacement lands; others acknowledged they were aware of this when polling to move forward, and though this was still the right choice. If we did not know that library vendors would be relying on the Zombie Names clause, there may have been more objections.
Final tally: 13 forward to POLL, 1 Neutral-but-concerned.
Conclusion: forward to the next electronic poll to send to LWG.
Poll taken: [P2972R0]
Poll results: [P3020R0]
Conclusion: Forward to LWG
Adopted into Working Draft N4971.
See paper [P2872R3] for a more detailed discussion and proposed wording to remove this facility from C++26.
SG16 reviewed P2872R0.
Giuseppe asked if the paper includes removal of
std::wbuffer_convert
.
Alisdair confirmed that it does.
Alisdair explained that these were deprecated because the example for
std::wstring_convert
used
another deprecated feature,
std::codecvt_utf8
and, due to
other underspecification concerns, no one was motivated to fix them.
Alisdair asked if SG16 is the right group to address this.
PBrett responded affirmatively and stated that SG16 is the group that
misunderstands wchar_t
the
least.
Alisdair noticed some issues with the paper and concluded that updates are required before the paper is ready for any action to be taken on it.
Approved for plenary poll with minor edits.
Adopted into Working Draft N4981.
See paper [P2873] for a more detailed discussion and proposed wording to remove this facility from C++26.
SG16 reviewed P2873R0.
Tom explained that these facets were deprecated because they convert to and from UTF-8 in char-based storage rather than between the multibyte encoding like the non-deprecated facets do.
Tom reported that
char8_t
-based replacements were
added as replacements, but those were a mistake because they won’t be
used by char
-based streams
anyway.
[ Editor’s note: [LWG3767] tracks
deprecating the char8_t
-based
facets. ]
PBrett asked for any objections to removal.
No objections were reported.
Corentin spoke in favor of removal.
A factory function to create path names from UTF-8 sequences of
char
was part of the original
filesystem library adopted for C++17 ([P0218R1]). However, this was the only
string-based factory function, as the preferred interface is to simply
construct a path with a string of the corresponding type/encoding. This
factory function was deprecated in C++20 with the addition of
char8_t
and the ability to now
invoke a specific constructor for UTF-8 encoded (and typed) strings. See
[P0482R6] for details.
The legacy API continues to function, but is more cumbersome than necessary. There appears to be no compelling case that the API is a risk through misuse, although the behavior is undefined if fed malformed UTF-8.
While it does no active harm, there is always a cost to maintaining text in the standard. The application of zombie names means that even if we remove this clause from Annex D in C++26, Standard Library vendors are likely to continue shipping to meet customer demand for some time to come. In the meantime, the current specification does not follow library wording best practices, and should be updated to better specify the Requires: clauses ([P2874R1]).
This component was reviewed by telecon, achieving LEWG consensus for removal in C++23. However, the author ran out of time to complete the large paper handling all Annex D removals, and new information has since come to light with issue [LWG3840] requesting undeprecation of this function.
After some discussion there was little appetite for undeprecating
filesystem::u8path
. It is the
only standard library interface that requires data provided in
char
-based storage to be encoded
in a different character encoding than the execution character set or
the encoding used for character and string literals.
For those that intentionally store UTF-8 data in
char
-based storage and would
prefer not to use a deprecated interface, an equivalent to
filesystem::u8path
can be
implemented in a few lines of code:
inline auto myu8path(const char* s) {
::u8string u8s(s, s+std::strlen(s));
stdreturn std::filesystem::path(u8s);
}
SG16, the Unicode and Text Study Group, is evaluating approaches to
enable restricted aliasing support for
char8_t
such that data in
char-based storage could be passed to a
char8_t
-based interface without
having to perform a copy as in the example code above; [P2626R0] is one such proposal.
SG16 observed that [P2626R0] aims to solve the root issue behind this problem, and that we should not remove a feature until it has co-existed at least one standard release with the facility to migrate to. There was also no enthusiasm for undeprecation, and a general leaning towards removal in due course, maybe C++29. They strongly recommend abiding by the status quo on this function for C++26.
Some folks mentioned using this interface, and how awkward it is to write code that is portable across multiple standards that does not rely on deprecated features; that problem would go away if we undeprecated this API, that behaves exactly as they expect.
Conversely, there is a desire to remove a potential source of confusion now that there is a type-safe interface that properly reflects the text encoding.
It was observed that it might be difficult to gain consensus in either direction — undeprecation or removal — and this feature may remain in limbo (Annex D) for many standards.
As the goal of this paper is to try to move deprecated features out of limbo, there was consensus to send this feature back to SG16 to consider their preferred direction for the long term future of this function.
While it does no active harm, there is always a cost to maintaining
text in the standard. This is similarly reflected in the C Standard,
that initially deprecated the
ATOMIC_VAR_INT
macro (marked it
as obsolescent) in C17, and is actively looking to remove it from the
C2X Standard, per the paper WG14:N2390. We should strongly consider
removing this macro, but perhaps as part of a broader paper to update
our reference to the C23 Standard Library.
The original API to initialize atomic variables from C++11 was deprecated for C++20 when the atomic template was given a default constructor to do the right thing. See [P0883R2] for details.
The legacy API continues to function, but is more cumbersome than
necessary. There appears to be no compelling case that the API is a risk
through misuse. However, if updating our reference to the C23 library
removes the ATOMIC_VAR_INT
macro, we might want to consider this removal for C++26.
Additionally, the volatile qualified member functions of the
atomic
class template were
deprecated for C++20 by paper [P1831R1]. Their removal should be
considered as part of [P2866] proposing
removal of deprecated volatile operations.
Confirmed there were no concerns, and submitted for electronic poll to forward to LWG.
Poll taken: [P3053R0]
Poll results: [P3054R0]
Conclusion: Forward to LWG
Needs a rationale for Annex C wording, and awaiting approval of Core parts before paper can proceed to a plenary poll.
Thanks to Michael Park for the pandoc-based framework used to generate this paper from extended markdown source.
Special thanks for Matt Godbolt for Compiler Explorer, that made it incredibly simple to test deprecated code samples across a variety of compilers, ancient and modern. This paper would be much less informed without the rapid testing it enabled.
shared_ptr
Atomic Access APIs
From C++26. wstring_convert
From C++26. polymorphic_allocator::destroy
For C++26. relops
From C++26. u8path
Overloads From C++26. iterator
Class Template From
C++26.