This document enumerates all the major changes that have been applied to the C++ working draft since the publication of C++17, up to the publication of the C++20 DIS. Major changes are those that were added in the form of a dedicated paper, although not all papers are mentioned individually. The remaining papers are listed summarily below. Issue resolutions from the CWG or LWG issues lists are generally not included, but the containing papers are part of the summary listing. Defect reports that are not part of the published International Standard are marked with a “DR” superscript.
Document | Summary | Examples, notes |
---|---|---|
P0619R4 | Removal of various deprecated features |
The following features that were already deprecated in C++17 are now removed:
|
P1236R1 | Only two’s complement representation for signed integers | As of C++20, the only permitted representation for signed integers is two’s complement. Previously, no representation was specified, but due to size and layout constraints, the only possible ones were two’s complement, ones’ complement, and sign-magnitude. Support for the latter two has now been removed. |
P0767R1 | Deprecate the notion of a “POD” type | The notion of a “plain-old data” (POD) type has been superseded by the more granular notions of trivial and standard-layout, and this change removes this notion from the main language specification (though it is retained as deprecated in Annex D). |
P0806R2 | Deprecate the implicit lambda capture of this via [=] |
The capture of this via [=] is now deprecated,
since it is irregular and potentially confusing with [=, *this] .
The capture should now be spelled [=, this] . See also P0409R2 below. |
P1161R3 | Deprecate the comma operator in subscripting expressions | The syntax a[x, y, z] is now deprecated; if this functionality
is desired, it should be spelled a[(x, y, z)] . Eventual
removal of the deprecated expression would open the door to extensions to
the subscripting expression. |
P1152R4, P1831R1 | Deprecate certain volatile qualifications |
The volatile qualifications in certain contexts where they
would be of questionable value or outright broken are now deprecated. (This
includes certain operands of increment/decrement and assignment expressions,
function parameters, function return types, and the types of structured
bindings.) |
P0966R1 | Deprecate shrinking basic_string::reserve |
The default argument of the parameter of
basic_string::reserve is removed and the function no longer shrinks
capacity. The behaviour was inconsistent with vector::reserve and
redundant with basic_string::shrink_to_fit . A deprecated
zero-parameter overload has been added to Annex D.
|
These are features that may happen to you without your knowledge or consent.
Document | Summary | Examples, notes |
---|---|---|
Core: P0734R0, P0857R0, P1084R2, P1141R2, P1452R2, P1616R1, P1972R0, P1980R0, P2092R0, P2104R0, P2113R0; Library: P0898R3, P1248R1, P1474R1, P1754R1, P1878R1, P1964R2, P2102R0. | Concepts | Concepts extend C++’s template facility with a way to constrain a template’s parameters. The constraints take part in overload resolution. |
P0912R5, P2107R0 | Coroutines | Coroutines are a new kind of control flow that extends the notion of a function. |
P1103R3, P1502R1, P1766R1, P1811R0, P1815R2, P1703R1, P1779R3, P1857R3, P1874R1, P1979R0, P2109R0, P2115R0 | Modules | Modules offer a new way to organize source code that is not based on textual inclusion in the way header inclusions were, but instead allows for a principled specification of component boundaries. |
P0515R3, P0905R1, P1120R0, P1185R2, P1186R3, P1630R1, P1614R2, P1855R0, P1946R0, P1959R0, P2002R1, P2085R0 | Three-way comparison (“spaceship”) and defaulted comparisons |
The value of the expression a <=> b describes which one of
a < b , a == b , and a > b
is true.A key part of this feature is that classes that provide this operator can have all of the six traditional, binary relational operators defined implicitly. |
These are features where you would know if you were using them.
Document | Summary | Examples, notes |
---|---|---|
P0329R4 | Designated initializers | struct X { int a; int b; }; X x { .b = 10 }; |
P0732R2, P1907R1 | Class-types in non-type template parameters |
Non-type template parameters can now be of class type:
struct X { /* ... */}; template <X Value> struct Y;
Certain restrictions apply to ensure that value identity can be established reliably.
These new kinds of non-type parameters are lvalues, unlike the existing non-class ones.
|
P0840R2 | [[no_unique_address]] |
An attribute that provides language support for empty or overlapping member objects. Previously, this effect was often achieved by using overlapping base class layouts (“empty base optimisation”). |
P0479R5 | [[likely]] , [[unlikely]] |
Attributes to guide branch prediction. Already wide-spread as vendor extensions. |
P1007R3 | assume_aligned |
A special language-support function that promises to the implementation that a pointer is aligned in a certain way (with undefined behaviour if this is not in fact true at runtime), which allows better code generation (e.g. vectorised instructions; omission of preambles). Already wide-spread as vendor extensions. |
P1143R2 | constinit |
The new constinit keyword specifies a variable to be
constant-initialized (and the program would be ill-formed if this is
not possible). The variable can still be mutable, and indeed this is
the key difference from a constexpr variable. Having
constant initialization suffices to avoid any form of static
initialization problems, and also allows local static variables to
omit a synchronization guard on access (since there is no dynamic
initialization that any thread would need to wait for).
|
P1073R3, P1937R2 | consteval |
The new consteval keyword specifies a function as an
“immediate function”, whose invocation is always a
constant expression (and which thus never requires code to be
emitted from the translation). Contrast this with constexpr
functions, which may, but are not required to be, used as
constant expressions.
|
P0595R2 | is_constant_evaluated |
A special language-support function that tells whether the caller is in a constant evaluation. This allows library implementations to provide a constexpr-implementation as well as an optimised runtime implementation of the same function (whereas the constexpr implementation alone would not have optimal runtime performance, if it turned out to be needed at runtime). |
P0722R3 | A destroying operator delete |
A new way to provide a deallocation function (operator delete ,
taking a parameter of type std::destroying_delete_t ) with the
effect that a delete-expression that would choose such a function
does not call the destructor; instead, the deallocation function
itself is required to call the destructor. See the paper for examples why
this might be desirable.
|
P0784R7 | Constexpr new /delete |
Dynamic object creation and destruction may now appear in constexpr
contexts, as long as every created object is destroyed. This allows, say,
the use of a local std::string variable in the body of a constexpr
function.
|
P0476R2 | bit_cast |
Despite its library-looking name, this is a core language facility
that creates objects whose object representation is copied from an
existing object. Importantly, the target type need not be
default-constructible. Attempts to achieve this by other means, while
very common, often run into undefined behaviour. Example:
std::uint32_t n = std::bit_cast<std::uint32_t>(1.5f);
|
P1099R5 | using enum |
A way to introduce the enumerator names of a scoped enumeration. |
Document | Summary | Examples, notes |
---|---|---|
P0896R4, P1252R2, P1035R7, P1243R4, P1391R4, P1394R4, P1456R1, P1523R1, P1716R3, P1739R4, P1862R1, P1870R1, P1871R1, P1970R2, P1983R0, P1994R1, P2091R0, P2106R0 | Ranges |
Ranges are a new model that improves on pairs of iterators. This feature consists
of new taxonomy, new concepts, and new versions of the familiar standard library
algorithms that live in namespace std::ranges .
|
P0355R7, P1361R2, P1466R3, P1650R0, P1981R0, P1982R0 | Calendars and time zones |
A large library addition to <chrono> for civil time
(calendars). For example: auto date = 2016y/May/29;
|
P0645R10, P1361R2, P1652R1, P1868R2, P1892R1 | Text formatting |
std::string s = std::format("{}", "Hello, world");
|
P1135R6, P1643R1, P1644R0, P1865R1 | Synchronization | Waiting, notifications, semaphores, latches, barriers. |
P0631R8 | Mathematical constants |
Variable templates for many mathematical constants, e.g.
std::numbers::pi_v<float> , and concrete constants
for double , e.g. std::numbers::pi .
|
P1208R6 | source_location |
A proper library type that exposes the information provided by the __LINE__
and __FILE__ macros, the __func__ variable, and column number.
|
P0122R7, P1085R2, P1024R3, P1227R2, P1394R4, P1872R0, P1976R2, P2116R0 | New class template: span |
A span is a light-weight reference to a contiguous range (mutable or const);
essentially a “pointer and size”: A span<T> is like a
T* p and a size N such that p[i] is valid for
i in [0, N ). It is similar in purpose (and pitfalls) to
C++17’s string_view , which is a special kind of span adapted
to strings.
|
P0660R10, P1869R1 | New classes: stop_token , jthread |
Mechanisms for a thread manager class that joins the thread on destruction, and for interrupting the running thread. |
P0019R8, P1123R0 | New class template: atomic_ref |
Atomic operations on non-atomic objects. |
P0550R2, P0777R1 | Transformation trait: remove_cvref |
A composition of remove_cv and remove_reference .
Previously, the slightly different decay had been popular for
this use case, even though it does too much. Existing uses of decay
in the specification have been replaced with the more appropriate transformations.
|
P0318R1 | Transformation traits: unwrap_reference , unwrap_ref_decay |
Traits to work with reference_wrapper : unwrap_reference_t<T>
is U& if T is reference_wrapper<U> , and
T otherwise. unwrap_ref_decay first applies decay
before unwrapping. The motivating use case is the specification of make_pair ;
these traits allow users to write functions with analogous handling of reference_wrapper .
|
P0887R1 | Transformation trait: type_identity |
type_identity_t<T> is T ; useful when a template parameter
is required in a non-deduced context.
|
P0758R1 | Type trait: is_nothrow_convertible |
Like is_convertible , but does not throw.
|
P1357R1 | Type traits: is_bounded_array , is_unbounded_array |
|
P0466R5 |
Type traits: is_layout_compatible ,
is_pointer_interconvertible_base_of ,
is_pointer_interconvertible_class ,
is_corresponding_member
|
|
P1115R3, P1209R0 | Free functions erase , erase_if |
Free functions to provide a simple, uniform interface for erasing elements from a container. The functions return the number of erased elements; see also P0646R1 below. |
P1227R2, P1970R2 | Free functions size , ssize |
One is signed, the other isn’t… |
P0463R1, P1612R1 | Endianness detection |
An enum endian whose members endian::native ,
endian::little , endian::big describe the
implementation’s endianness.
|
P0053R7, P0753R2 | Synchronized, buffered ostream |
A buffering ostream wrapper, basic_osyncstream , that causes all
output to be emitted atomically to the wrapped ostream. Example:
std::osyncstream(std::cout) << a << b << "foo" << c << '\n';
Unlike in the unwrapped version, concurrent writes to cout never interleave.
|
P0769R2 | shift algorithms |
New algorithms for shifting the elements of a range:
shift_left , shift_right
|
P0556R3, P1355R2, P1956R1 | Functions for integral power-of-2 operations |
has_single_bit (i.e. is a power of two),
bit_ceil , bit_floor ,
bit_width
|
P0553R4 | Functions for bit operations |
Rotation (rotl , rotr ),
population count (popcount ),
count of number of successive zeros or ones from left or right
(countl_zero , countl_one ,
countr_zero , countr_one ).
|
P0811R3 | Functions midpoint , lerp |
Interpolation functions. std::midpoint(a, b) computes
essentially a + b / 2 , but works with integers,
floating point numbers, and pointers. std::lerp
computes arbitrary linear interpolation. Both are correct even in
corner cases.
|
P0586R2 | Function templates cmp_equal , cmp_less , etc. |
These functions provide integral comparisons that produce the mathematical
result even when the operands have different types. For example,
cmp_less(-1, 0U) is true , whereas
-1 < 0U is false (due to arithmetic conversions).
|
P1020R1, P1973R1 | Function templates make_unique_for_overwrite ,
make_shared_for_overwrite ,
allocate_shared_for_overwrite |
The existing smart pointer creation functions make_unique ,
make_shared and
allocate_shared use value-initialization when called with no
constructor arguments (equivalent to new T() ). This new feature
adds functions make_unique_for_overwrite ,
make_shared_for_overwrite ,
and allocate_shared_for_overwrite , which take no constructor
arguments and use default-initialization (equivalent to new T ).
This avoids unnecessary initialization in situations where the initial value
is never read.
|
P0356R5, P1651R0 | Function template bind_front |
A simpler, more predictable version of bind that
only binds arguments on the left.
|
P0325R4 | Function template to_array |
|
P0653R2 | Function template to_address |
A well-defined replacement for addressof(*p) that works
even when p does not point to a constructed object.
|
P0591R4 | Utilities for the uses-allocator construction | |
P1001R2 | New execution policy “unsequenced” | Unsequenced execution allows for vectorization (even on a single thread). |
Document | Summary | Examples, notes |
---|---|---|
P0482R6, P1423R3 | New type: char8_t |
The type char8_t is analogous to the existing types char16_t and
char32_t , i.e. a fundamental, unsigned integral type, sufficient to store
one UTF-8 code unit. As a breaking change, the types of u8 character literals
(C++17, e.g. u8'a' ) and u8 string literals (C++11, e.g.
u8"foo" ) are now char8_t and array of char8_t ,
respectively; previously they were (array of) char . This breakage was deemed
to be minor, since both of those features had not been widely used. This change enables
overload resolution to distinguish intended UTF-8 from native encoding, which previously
was only distinguished by the choice of literal, but not by the type of the literal value.
|
P1041R4 | Makes char16_t /char32_t literals be UTF-16/32 |
This requires that char16_t literals (e.g. u"foo" ) be
encoded as UTF-16 and char32_t literals (e.g. U"foo" )
as UTF-32. This in analogy with u8 literals (which are now
char8_t literals), and which have already been required to be
valid UTF-8.
|
P0668R5, P0735R1, P0982R1 | Revising the memory model | The memory model has been revised. |
P0306R4, P1042R1 | Enhancements of variadic macros |
Variadic macros are now allowed to be invoked with zero variadic arguments (this was
previously accepted as an extension by many compilers). Within a variadic macros, the
new feature __VA_OPT__(content)
can now be used, which expands to nothing if there are no variadic arguments, and
to content otherwise. A typical use case is for a comma that is
required if and only if there are variadic arguments: define F(A, B, ...)
vfunc(A, B __VA_OPT__(,) __VA_ARGS__) |
P0614R1 | Range-based for statements with initializer |
A range-based for statement may now contain an additional initializer:
for (Data d = FetchData(); const Row& row : d.rows()) { use(row); }
|
P0683R1 | Default member initializers for bit-fields |
Bit-fields can now have default member initializers: struct X { int a : 2 {-2}; int b : 2 = 1; };
|
P0960R3, P1975R0 | Aggregate initialization from a parenthesized list |
Aggregates can now be initialized with round parentheses instead of curly braces:
struct T { int a, b, c; }; T x(1, 2); A (motivating) consequence is that
make_unique and emplace now work with aggregate types.
|
P0428R2 | Template head for generic lambdas |
A generic lambda may now use a template head instead of (and in addition to)
auto parameters, e.g.: []<typename T>(T a, T& b, const T& c) {} |
P0624R2 | Default-constructible and assignable stateless lambdas | Objects of stateless closure type (i.e. the type of a lambda without any captures) can now be default-constructed and assigned. This allows uses such as lambdas as container predicates. |
P0315R4 | Lambdas in unevaluated contexts |
Lambdas may now appear in unevaluated contexts (e.g. using F =
decltype([](int a, int b) { return a + b; }); ). Combined with the
above P0624R2, this makes lambdas usable in a wider range of situations.
|
P0780R2, P2095R0, | Pack expansion in lambda init-capture |
An init-capture may now introduce a pack:
template <typename ...Args> void f(Args... args) {
auto x = [...brgs = std::move(args)](){}; } |
P0409R2 | Lambda capture [=, this] |
It is now allowed to spell the lambda capture [=, this] explicitly.
Previously, the “this ” was considered redundant and forbidden.
See also P0806R2 above.
|
P0961R1, P0969R0, P1091R3, P1381R1 | Improvements for structured bindings | P0961R1 and P0969R0 are intended as a defect resolution against C++17. |
P1009R2 | Array size deduction in new-expressions |
This allows new int[]{1, 2, 3} , which was previously ill-formed.
This change is intended as a defect resolution against C++17.
|
P0702R1, P0739R0, P1814R0, P1816R0, P2082R1 | Class template argument deduction (“CTAD”) | Various tweaks and improvements. Some of these are defect resolutions against C++17 (P0702R1, P0739R0). Aliases and aggregate templates can now use CTAD. |
P1825R0 | Copy elision and move semantics |
Rvalue reference variables can now be moved implicitly in return statements.
This change is intended as a defect resolution against C++17.
|
P0634R3 | Fewer required typename disambiguations |
This change removes the need to disambiguate a dependent name as a typename
via the typename keyword from several places where this is
already unambiguous. This removes some redundant ceremony from template code.
|
P0846R0 | ADL and function templates that are not visible |
This change fixes a long-standing, somewhat obscure situation, where it was not
possible to provide explicit template arguments for a function template that is
meant to be found through ADL when the name was not known to refer to a function
template. For example, f<A>(a) would have been treated as a
binary expression f < A rather than as a template name
f<A> . Previously, work-arounds were required to make ADL work
in such a situation.
|
P0692R1 | Access checking on specializations |
This change fixes a long-standing, somewhat obscure situation, where it was not
possible to declare a template specialization for a template argument that is a
private (or protected) member type. For example, given
class Foo { class Bar {}; }; , the access Foo::Bar
is now allowed in template<class> struct X;
template<> struct X<Foo::Bar>; .
|
P0892R2 | explicit(bool) |
The explicit specifier now accepts an optional boolean parameter
(where explicit(true) is equivalent to explicit and
explicit(false) is equivalent to the absence of explicit ),
which simplifies generic code where explicitness is “forwarded” from
template parameters in some sense. |
P1301R4 | An optional string for [[nodiscard]] |
A new form of the attribute now allows specifying a text (e.g. guidance for
a user who is erroneously discarding a result), e.g.
[[nodiscard("did you mean to call a different function")]] .
|
P0848R3 | Conditionally trivial special member functions | It is now possible to provide special member functions in both defaulted and non-defaulted forms at once, provided the declarations are constrained in a mutually exclusive way. This simplifies generic code where defaultedness is “forwarded” from template parameters in some sense. |
P1094R2 | Nested inline namespaces |
Inline namespaces may now appear inside a nested namespace declaration:
namespace a::inline b::c {}
|
P1002R1, P1064R0, P1327R1, P1330R0, P1331R2, P1668R1 | constexpr in the core language |
Additional core language facilities are now allowed in constexpr functions:
try /catch ,
virtual function calls,
dynamic_cast /typeid ,
changing the active union member,
trivial default initialization,
asm-definitions.
|
P0202R3, P0415R1, P0858R0, P0879R0, P0972R0, P0980R1, P1004R2, P1006R1, P1065R2, P1023R0, P1032R1, P1424R1, P1645R1 | constexpr in the library |
Many more library functions (including member functions) are
now constexpr : algorithms, utilities, complex ,
swap , chrono , string ,
vector ,
pointer_traits , INVOKE ,
array comparisons, pair /tuple ,
numeric algorithms.
There is also a new notion of a constexpr iterator.
|
P0600R1 | nodiscard in the library |
Several library (member) functions are now annotated with the
[[nodiscard]] attribute (for example, vector::empty ).
|
P0935R0 | Remove accidentally-explicit default constructors |
This large change replaces many explicit constructors that have default
arguments, such as explicit foo(Alloc a = Alloc()); , with two
overloads, such that the resulting default constructor is not explicit.
Previously, the one-parameter constructor was a default constructor, but
because it was explicit, reasonable initializations such as
foo x = {}; had been ill-formed. This was unintended, since
explicit was only meant to inhibit implicit conversions.
|
P0919R3, P1690R1 | Heterogeneous lookup for unordered containers |
Analogous to heterogeneous lookup for ordered containers in C++14, this change
allows transparent predicates to be defined and used in unordered containers.
For example, an unordered_map with key string that
uses transparent predicates can look up a string_view or a
const char* without constructing a string object for
the lookup. The details are more complicated than for ordered containers, since
equality and hashing need to be compatible even when the types differ.
|
P0458R2 | Element existence in associative containers (“contains ”) |
A new member function, m.contains(key) , equivalent to
m.find(key) != m.end() , for all associative containers.
|
P0646R1 | Return element counts from list , forward_list operations |
The modifying member functions remove , remove_if and
unique of list and forward_list now
return the number of removed elements.
|
P0457R2 | Prefix/suffix checking for strings |
The class templates basic_string_view and basic_string
have new member functions starts_with and ends_with
that test whether the string starts/ends with the given prefix/suffix (string
or single character).
|
P0674R1 | make_shared for arrays |
The make_shared creation function can now be used for array types, e.g:
make_shared<T[]>(N); (Array types are supported by shared_ptr
since C++17.)
|
P0020R6 | Floating-point atomic |
atomic<float> , atomic<double> ,
atomic<long double>
|
P0718R2 | Atomic shared_ptr and weak_ptr |
There are now partial specializations atomic<shared_ptr<T>>
and atomic<weak_ptr<T>> that allow atomic access to a shared
or weak pointer. This replaces the existing free function overloads
shared_ptr<T> atomic_load(const shared_ptr<T>*) etc.,
which were fragile and error-prone. The old free function overloads are now deprecated.
|
P0528R3, P1123R0 | Atomic compare-and-exchange in the presence of padding |
This change makes it a requirement that compare-and-exchange for an atomic
type atomic<T> works even when the type T
contains padding bits. That is, whether the expected value equals the current
value is no longer allowed to depend on unspecified padding; implementations
may need to do extra work to make this happen (e.g. always store a predictable
bit pattern in the padding, or use a masked comparison).
|
P0439R0 | Make memory_order a scoped enumeration |
Instead of std::memory_order_relaxed we now have
std::memory_order::relaxed , etc.. The old names are
provided as free constants for compatibility.
|
P0616R0 | Use std::move in <numeric> algorithms |
Algorithms such as accumulate used to be specified as having
the binary operation called like acc = op(acc, *it) . This has
now changed to acc = op(std::move(acc), *it) .
|
P0408R7 | Efficient access to the buffer of basic_stringbuf |
API additions to basic_stringbuf and string-stream classes
that allow moving the buffering string in and out.
|
P1148R0 | Comprehensive review of [strings] |
A thorough cleanup of the specification of char_traits ,
basic_string_view , and basic_string . This
resolves numerous LWG issues.
|
Document | Summary | Examples, notes |
---|---|---|
P0941R2, P1353R0, P1902R1 | Feature test macros | Feature test macros are now part of the working paper. This is not relevant to the published International Standard, but it enables vendors to support upcoming language revisions incrementally and inform users which features are provided by the implementation. The feature test macros were previously maintained in the separate SD-6. |
P0754R2 | The <version> header |
The new header <version> is provided. It is formally empty and
not relevant to the published International Standard, but it provides a standardized
place for implementation-defined information. Previously, the now-removed header
<ciso646> (see P0619R4 above) was frequently and informally used
for this purpose. The new feature test macros (see P0941R2 above) are defined in
this header (as well as in their contextually appropriate place).
|
P0788R3; P1458R1, P1459R1, P1460R1, P1462R1, P1463R1, P1464R1, P1622R3, P1686R2, P1718R2, P1719R2, P1720R2, P1721R2, P1722R2, P1723R2, P2045R1. | Replace Requires with Constraints, Mandates, Preconditions in the specification | A change to the formal specification of the library only: the old Requires element, which was serving multiple roles, is now obsolete and replaced by three new elements, Constraints (statically checked, affects overload resolution), Expects (preconditions whose violation results in undefined behaviour), and Mandates (statically checked conditions whose violation makes the program ill-formed). This should not have any observable effect, but it makes it clearer which requirements are diagnosed, which are the user’s responsibility, and which affect overload resolution (but do not produce errors per se). |
P0551R3 | Restrict use of std functions and function templates |
A significant restriction in what users are allowed to do with standard library functions and function templates: Users are no longer allowed to specialize standard library function templates, and in general to take the address of a standard library function (unless the function is explicitly specified as addressable). This improves implementer freedom greatly to, say, implement a function as an overload set or a template. It marks a significant clarification of policy: functions in the standard library are in general only supposed to be understood as valid call expressions, not literally as declared functions. |
P1025R1 | Update reference to Unicode | Adds an undated reference to ISO/IEC 10646, and replaces “UCS4” with ”UTF-32“. |
The following papers were moved at committee meetings, but their contents are too specific to call out as separate features: P0339R6, P0340R3, P0357R3, P0388R4, P0475R1, P0487R1, P0602R4, P0608R3, P0641R2, P0655R1, P0704R1, P0738R2, P0759R1, P0771R1, P0809R0, P0883R2, P0899R1, P1008R1, P1131R2, P1139R2, P1165R1, P1207R4, P1285R0, P1522R1, P1638R1, P1908R1, P1960R0, P1961R0, P1963R0, P1965R0, P2101R0. Additionally, the following otherwise unlisted papers were accepted as defect resolutions against C++17: P0588R1, P0593R6, P0682R1, P0727R0, P0859R0, P0929R2, P0962R1, P1164R1, P1286R2, P1771R1, P1957R2.
The following papers contain issues that have been accepted as defect reports. CWG issues are handled by P0710R1, P0711R0, P0817R0, P0818R1, P0968R0, P1113R0, P1114R0, P1350R0, P1358R0, P1359R0, P1510R0, P1969R0, P1968R0, P1971R0, P2103R0, P2108R0. LWG issues are handled by P0698R0, P0699R0, P0815R0, P0864R0, P0888R0, P1003R0, P1082R0, P1224R0, P1457R0, P1724R0, P1917R0, P2051R0, P2117R0. Only specific issues may have been selected from each paper; the meeting minutes contain the details. The complete accumulation of accepted issues is published in the regularly updated CWG issues list and LWG issues list.
The committee maintains a list of issues (see links above) which contain suggestions for improvements in the normative wording (clarifications, simplifications, corrections, etc.). When an issue is accepted that affects the published standard (not just the new work in progress), we have a defect report. The complete specification of C++ consists of the latest published document as amended by the resolutions of all subsequent defect reports. The resolution of a defect report is also incorporated into the working paper (as applicable), and thus the next published revision of the Standard no longer has that particular issue.
Therefore, the answer to the question of, say, “what is a valid C++14
program?” changes over time, up until the publication of C++17, and so forth. In
practice, the situation is a bit more complicated when compiler vendors offer conformance
modes for specific language revisions (e.g. -std=c++11
,
-std=c++17
). Vendors may consider defect resolutions to apply to any
historic revision that contains the defect (whereas ISO considers only the most recent
publication as the Standard).
Papers that have been applied to the working draft since the publication of C++20 and that are intended as defect reports are annotated with “DR” in the above change summary. Defect reports against C++20 that concern older (pre-C++20) content are not called out here specifically, nor are defects against C++17 whose resolutions are included in C++20. The full history of accepted issues together with the Standard revisions to which they apply is implicit in the CWG and LWG issues lists, but it is difficult to present explicitly.