This document enumerates all the major changes that have been applied to the C++ working draft since the publication of C++14, up to the publication of C++17. 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 | 
|---|---|---|
| N4086 | Remove trigraphs | The sequence ??!no longer means|. Implementations may offer trigraph-like features as part of their input encoding. | 
| P0001R1 | Remove register | The registerkeyword remains reserved, but it no longer has any semantics. | 
| P0002R1 | Remove ++forbool | Increment ( ++) prefix and postfix expressions are no longer valid for operands of typebool. | 
| P0003R5 | Remove throw(A, B, C) | Dynamic exception specifications of the form throw(A, B, C)are no longer valid. Onlythrow()remains as a synonym fornoexcept(true). Note the change in termination semantics. | 
| P0386R2 | Deprecate redeclaration of static constexpr class members | Given struct X { static constexpr int n = 10; };,int X::n;is no longer a definition, but instead a
            redundant redeclaration, which is deprecated. The memberX::nis implicitly inline (see below). | 
| N4190 | Remove auto_ptr,random_shuffle,
            old parts of<functional> | Features that have been deprecated since C++11 and replaced with superior components are no longer included. Their names remain reserved, and implementations may choose to continue to ship the features. | 
| P0004R1 | Remove deprecated iostream aliases | Same as above | 
| P0302R1 | Remove allocator support from function | The polymorphic function wrapper functionno longer has constructors that
            accept an allocator. Allocator support for type-erasing, copyable types is difficult, and
            possibly not implementable efficiently. | 
| P0063R3 (see below) | Deprecate C library headers | The following headers of the “C library” (this is the term
            for a part of the C++ standard library, not a part of the C
            standard!) are now deprecated: <ccomplex>,<cstdalign>,<cstdbool>,<ctgmath>. Note that the header<ciso646>is not deprecated. | 
| P0174R2 | Deprecate old library parts | These library components are now deprecated: allocator<void>,raw_storage_iterator,get_temporary_buffer,is_literal_type,std::iterator. | 
| P0618R0 | Deprecate <codecvt> | The entire header <codecvt>(which does not
            contain the classcodecvt!) is deprecated, as are the
            utilitieswstring_convertandwbuffer_convert.
            These features are hard to use correctly, and there are doubts whether they
            are even specified correctly. Users should use dedicated text-processing
            libraries instead. | 
| P0371R1 | Deprecate memory_order_consumetemporarily | The current semantics of “consume” ordering have been found inadequate, and the ordering needs to be redefined. While this work is in progress, hopefully ready for the next revision of C++, users are encouraged to not use this ordering and instead use “acquire” ordering, so as to not be exposed to a breaking change in the future. | 
| P0521R0 | Deprecate shared_ptr::unique | This member function suggests behaviour that is not actually provided. | 
| P0604R0 | Deprecate result_of | Use the new trait invoke_resultinstead. | 
These are features that may happen to you without your knowledge or consent.
| Document | Summary | Examples, notes | 
|---|---|---|
| P0012R1 | Exception specification as part of the type system | The exception specification of a function is now part of the
            function’s type: void f() noexcept(true);andvoid f() noexcept(false);are functions of two distinct
            types. Function pointers are convertible in the sensible direction. (But
            the two functionsfmay not form an overload set.) This
            change strengthens the type system, e.g. by allowing APIs to require
            non-throwing callbacks. | 
| P0135R1 | Guaranteed copy elision | The meaning of prvalue and glvalue has been revised, prvalues are no longer objects, but merely “initialization”. Functions returning prvalues no longer copy objects (“mandatory copy elision”), and there is a new prvalue-to-glvalue conversion called temporary materialization conversion. This change means that copy elision is now guaranteed, and even applies to types that are not copyable or movable. This allows you to define functions that return such types. | 
| P0035R4 | Dynamic allocation of over-aligned types | Dynamic allocation ( operator new) may now support over-aligned
            types, and a new overload of the operator takes an alignment parameter.
            It is still up to the implementation to choose which alignments to support. | 
| P0145R3 | Stricter order of expression evaluation | The order of evaluation of certain subexpressions has been specified more than it used to be. An important particular aspect of this change is that function arguments are now evaluated in an indeterminate order (i.e. no interleaving), which was previously merely unspecified. Note that the evaluation order for overloaded operators depends on how they are invoked: when invoked using operator syntax, the order is the same as for the built-in operator, but when invoked using function call syntax, the order is the same as for ordinary function calls (i.e. indeterminate). | 
These are features where you would know if you were using them.
| Document | Summary | Examples, notes | 
|---|---|---|
| N4267 | A u8character literal | A character literal prefix u8creates a character that
            is a valid Unicode code point that takes one code unit of UTF-8, i.e.
            an ASCII value:u8'x' | 
| P0245R1 | Hexadecimal floating point literals | Floating point literals with hexadecimal base and decimal exponent: 0xC.68p+2,0x1.P-126. C has supported this
            syntax since C99, andprintfsupports it via%a. | 
| N4295, P0036R0 | Fold expressions | A convenient syntax for applying a binary operator iteratively to the
              elements of a parameter pack: template <typename ...Args>
              auto f(Args ...args) { return (0 + ... + args); } | 
| P0127R2 | template <auto> | A non-type template parameter may now be declared with placeholder
            type auto.
            Examples:•   template <auto
            X> struct constant { static constexpr auto value = X; };•   Delegate<&MyClass::some_function> | 
| P0091R3, P0512R0, P0433R2, P0620R0, P0702R2DR, P0739R0DR | Class template argument deduction | The template arguments of a class template may now be deduced
            from a constructor. For example, pair p(1, 'x');definespaspair<int, char>(this is not
            an HTML error, the template arguments were omitted deliberately). The implicit
            deduction is complemented by a system of explicit deduction guides which
            allow authors to customise how the deduction happens, or forbid it. | 
| P0292R2 | Constexpr if | The new if constexpr (condition)statement
            selects based on a constant expression. Inside a template specialization, only the arm
            with the matching condition is instantiated. | 
| P0305R1 | Selection statements with initializer | The selection statements ifandswitchgain
            a new, optional initializer part:if (auto it = m.find(key);
            it != m.end()) return it->second;  | 
| P0170R1 | Constexpr lambdas | Lambda expressions may now be constant expressions: auto add =
            [](int a, int b) constexpr { return a + b; };
            int arr[add(1, 2)]; | 
| P0018R3 | Lambda capture of *this | Before: [self = *this]{ self.f(); }Now:[*this]{ f(); } | 
| P0386R2, P0607R0 | Inline variables | In a header file: inline int n = 10;All definitions refer to the same entity. Implied for static constexpr
            class data members. (This feature is backported onto existing library
            constants and used for new ones.) | 
| P0217R3, P0588R1DR, P0615R0, P0961R1DR,, P0969R0DR, CWG 2285DR | Structured bindings | auto [it, ins] = m.try_emplace(key, a1, a2, a3);Decomposes arrays, all-members-public classes, and user-defined types that follow a get<N>protocol likepair,tupleandarray. | 
| P0061R1 | __has_include | A preprocessor operator to check whether an inclusion is possible. | 
| P0188R1 P0189R1 P0212R1 | Attribute [[fallthrough]]Attribute [[nodiscard]]Attribute [[maybe_unused]] | A new set of standardised attributes. The attributes formally have no required semantics, but implementations are encouraged to emit or suppress the appropriate diagnostics (warnings). | 
| P0137R1 | launder | A language support tool (an “optimisation barrier”) to allow libraries to reuse storage and access that storage through an old pointer, which was previously not allowed. (This is an expert tool for implementers and not expected to show up in “normal” code.) | 
| P0298R3, LWG 2950DR | A byte type | A new type byteis defined in<cstddef>(not in<stddef.h>, and only in namespacestd!)
            which has the layout ofunsigned char, shares the aliasing
            allowances of the existing char types, and has bitwise operations defined. | 
| Document | Summary | Examples, notes | 
|---|---|---|
| P0226R1 | Mathematical special functions | The contents of the former international standard
            ISO/IEC 29124:2010 (mathematical special functions)
            are now part of C++. The functions were added only to <cmath>, not to<math.h>,
            and are only available in namespacestd. | 
| P0218R0, P0219R1, P0317R1, P0392R0, P0430R2, P0492R2, LWG 2956DR | Filesystem | The contents of the Filesystems Technical Specification are now part of C++. The filesystems library allows portable interaction with directories and directory-like structures (listing directory contents, moving files, etc.). It is largely modelled on POSIX, but flexible enough to be implementable for a wide variety of systems. | 
| P0024R2, P0336R1, P0394R4, P0452R1, P0467R2, P0502R0, P0518R1, P0523R1, P0574R1, P0623R0 | Parallelism | The contents of the Parallelism Technical Specification are now part of C++. This adds new overloads, taking an additional execution policy argument, to many algorithms, as well as entirely new algorithms (see below). Three execution policies are supported, which respectively provide sequential, parallel, and vectorized execution. | 
| P0024R2 | New algorithms | The Parallelism Technical Specification adds several new algorithms
            to the standard library. They are motivated by their potential for
            efficient parallel execution, but are available in the usual simple
            form as well: for_each_n,reduce,transform_reduce,exclusive_scan,inclusive_scan,transform_exclusive_scan,transform_inclusive_scan. Note thatreducelooks similar to the existingaccumulate, but does not
            guarantee any particular order of operations. | 
| P0220R1, P0254R2, P0403R1 | New type: string_view(andbasic_string_view) | The new string_viewclass is the preferred interface vocabulary
            type for APIs that need to view a string without wanting to take ownership or to
            modify it. It is constructible from char pointers, but all other classes that
            are string-like should offer conversions tostring_view. | 
| P0220R1, P0032R3, P0504R0 | New type: any | The type anytype-erases copyable objects. There are essentially
            three things you can do with anany: 1. put a value of typeTinto it. 2. Make a copy of it. 3. Ask it whether it contains a value of typeUand get that value out, which succeeds if and only ifUisT. | 
| P0088R3, P0393R3, P0032R3, P0504R0, P0510R0, LWG 2901DR | New class template: variant | A variant models a disjoint union (or discriminated union). A value of variant<A, B, C>contains one of anA,
            aB, or aCat any one time. | 
| P0220R1, P0307R2, P0032R3, P0504R0 | New class template: optional | An optional value. A optional<T>represents either aTvalue, or no value (which is signified by the tag typenullopt_t). In some respects this can be thought of as
          equivalent tovariant<nullopt_t, T>, but with a purpose-built
          interface. | 
| P0220R1 | New algorithm: sample | Samples at most nelements uniformly from a range. | 
| N4169 | invoke | A facility to uniformly invoke callable entities. This allows users
            to write libraries with the same behaviour as the standard’s
            magic INVOKErule. | 
| P0077R2, P0604R0 | is_invocable,is_invocable_r,invoke_result | Traits to reason about invocability and invocation results. | 
| P0067R5, P0682R1DR | Elementary string conversions | Functions to_chars,from_charsthat produce
            or parse string representations of numbers. These are intended to form
            an efficient, low-level basis for a replacement forprintfand iostream formatted operations. They follow idiomatic C++ algorithm
            style. | 
| N3911 | Alias template void_t | template <class...> using void_t = void;Surprisingly
            useful for metaprogramming, to simplify use of SFINAE. | 
| N4389 | Alias template bool_constant | template <bool B> using bool_constant =
            integral_constant<bool, B> | 
| P0013R1 | Logical operation metafunctions | Variadic metafunctions conjunction,disjunction, andnegationfor metaprogramming. These traits short-circuit in the
            metaprogramming sense: template specializations that are not required to
            determine the result are not instantiated. | 
| P0185R1 | Traits for SFINAE-friendly swap | New traits is_{,nothrow_}swappable,is_{,nothrow_}swappable_with. | 
| LWG 2911 | Trait is_aggregate | Whether a type is an aggregate. Useful for example to tell whether a generic type should be list- or non-list-initialized. | 
| P0258R2 | Trait has_unique_object_representations | This trait may be used to reason about whether certain value-based
            operations like comparison and hashing can be replaced with
            representation-based operations (e.g. memcmp). | 
| P0007R1 | as_const | Given an lvalue x,as_const(x)returns
            the const-qualified version. Does not bind to rvalues. | 
| N4280 | Non-member size,data,empty | The additional functions complement the existing free functions begin,endetc. to access containers and
            arrays in a uniform fashion. Note that unlikebegin/end, the new functions are not
            customisation points for anything and are only provided for convenience. | 
| P0025R0 | clamp | clamp(x, low, high)returns eitherxifxis within the interval[low, high],
            or the nearest bound otherwise. | 
| P0295R0 | gcdandlcm | Number-theoretic functions to compute the greatest common divisor and least common multiple of two integers. | 
| N4508 | Class shared_mutex | A reader-writer mutex, which can be locked in either shared or exclusive mode. | 
| P0154R1 | Interference sizes | Two new implementation-defined constants hardware_{con,de}structive_interference_sizethat effectively allow the platform to document its cache line sizes
            so that users can avoid false sharing (destructive interference) and
            improve locality (constructive interference). Two separate constants
            are defined to support heterogeneous architectures. | 
| P0220R1 | Tuple apply | Invokes a callable with arguments extracted from a given tuple. | 
| P0209R2 | Construction from tuples | A new function template make_from_tuplethat initializes
            a value of typeTfrom the elements of a given tuple. It
            is likeapplyapplied to a constructor. | 
| P0005R4, P0358R1 | Universal negator not_fn | A call wrapper that negates its wrapped callable. This works with callables
            of any arity and replaces the old not1andnot2wrappers. | 
| P0220R1 | Memory resources | A new set of components comprised of a memory resource base class
            for dynamically selectable memory providers, as well as three concrete
            implementations ( synchronized_pool_resource,unsynchronized_pool_resource,monotonic_buffer_resource).
            See next item for use cases. | 
| P0220R1, P0337R0 | A polymorphic allocator | An allocator that uses a memory resource, which can be changed
            at runtime and is not part of the allocator type. Also contains
            convenience type aliases like std::pmr::vector<T> =
            std::vector<T, polymorphic_allocator<T>>. | 
| P0220R1, P0253R1 | Searcher functors | Substring searcher functors implementing the Boyer-Moore and
            Boyer-Moore-Horspool algorithms, and a searchalgorithm
            using those functors. | 
| Document | Summary | Examples, notes | 
|---|---|---|
| N3928 | Single-argument static_assert | The static_assertdeclaration no longer requires
            a second argument:static_assert(N > 0); | 
| N4230 | Nested namespace declarations | namespace foo::bar { /* ... */ } | 
| N4051 | Allow typenamein template template parameters | template <template <typename> typename
            Tmpl> struct X;Previously, template template parameters
            were required to use the keywordclass. | 
| P0184R0 | Range-based fortakes separate begin/end types | The rewrite rule for for (decl : expr)now
            saysauto __begin = begin-expr; auto __end =
            end-expr;, as opposed toauto __begin =
            begin-expr, __end = end-expr;before.
            This prepares the range-basedforstatement for the new
            Ranges (work in progress). | 
| P0195R2 | Pack expansion in using-declarations | template <typename ...Args> struct X : Args... {
            using Args::f...; }; | 
| P0138R2 | Construction for values of fixed enums | A variable of a fixed enumeration Ecan now be defined
            withE e { 5 };and no longer requires the the more cumbersomeE e { E(5) };. | 
| P0522R0 | Relaxed matching rules for template template-parameters | Previously, template template arguments had to match the parameter exactly.
            Now templates with additional (defaulted) parameters, with parameter packs
            or with autoparameters are valid arguments, too. For example,template <template <int> class Tmpl> struct X;accepts an argumenttemplate <auto N, typename T = void> struct A; | 
| LWG2709 | Relaxed requirements for offsetof | Previously, use of the offsetofmacro with a type that is not
            standard-layout had undefined behaviour; now it is conditionally-supported. | 
| N3922 | New rules for autodeduction from braced lists | Previously, auto a{1, 2, 3}, b{1};was allowed and both
            variables were of typeinitializer_list<int>.
            Nowauto a{1, 2, 3};is ill-formed andauto b{1};declares anint. Note thatauto a = {1, 2, 3}, b = {1};remains unchanged and deducesinitializer_list<int>.
            This change is intended as a defect resolution against C++14. | 
| P0017R1 | Extension to aggregate initialization | List initialization can now aggregate-initialize base subobjects: Given aggregates struct base { int a1, a2; }; struct derived : base { int b1; };, the
            following initializations are now valid:derived{{1, 2}, 3},derived{{}, 3}. | 
| N4259 | uncaught_exceptions() | The function uncaught_exceptionis deprecated, the
            new functionuncaught_exceptionsreturns a count rather
            than a boolean. The previous feature was effectively unusable;
            N4152 explains the details. | 
| N4266 | Attributes in namespaces and enumerators | Namespaces and enumerators can now be annotated with attributes. This allows, for example, to deprecate namespaces or enumerators. | 
| P0028R4 | Attribute namespaces without repetition | This simplifies the use of attribute namespace qualifications when a namespace is used repeatedly. | 
| N4279 | Improved insertion for unique-key maps | m.try_emplace(key, arg1, arg2, arg3)does nothing ifkeyalready exists in the map, and otherwise inserts a new element constructed from the
            arguments. This interface guarantees that even if the arguments are bound to rvalue
            references, they are not moved from if the insertion does not take place. | 
| P0084R2 | Return type of emplace | Sequence containers whose emplace{,_front,_back}member function templates used to returnvoidnow
            return a reference to the newly inserted element. (Associative
            containers are not affected, since their insertion functions have
            always returned iterators to the relevant element.) | 
| P0083R3, P0508R0 | Splicing maps and sets | A new mechanism, node handles, has been added to the container library that allows transplanting elements between different map/set objects without touching the contained object. Moreover, this technique enables mutable access to key values of extracted nodes. | 
| P0272R1 | Non-const string::data | There is now a non-const overload of basic_string::datathat returns a mutable pointer. Moreover, C++17 allows writing to the
            null terminator, provided that the value zero is written. This makes
            the string classes a bit more convenient to use with C-style interfaces. | 
| P0156R0, P0156R2 | A variadic version of lock_guardcalledscoped_lock | A new, variadic class template scoped_lock<Args...>that locks multiple lockable objects at once (using the same algorithm
            aslock) and releases them in the destructor. Initially
            it was suggested to simply change the definition oflock_guardto become variadic, but this was discovered to be a breaking change, and
            so instead we now have a new class templatescoped_lockthat
            is strictly superior to the oldlock_guardand should be
            used instead. | 
| P0006R0 | Variable templates for traits | For every standard type trait foowith a single, static member
            constantfoo<Args...>::value, there is now a
            variable templatefoo_v<Args...>. | 
| P0152R1 | atomic::is_always_lock_free | A new static member constant is_always_lock_freethat
            documents whether the operations of a given atomic type are always lock-free.
            The existing non-static member functionis_lock_freemay
            give different answers for different values of the atomic type. | 
| P0220R1, P0414R2 | shared_ptrfor arrays | The class template shared_ptrnow supports C-style arrays
            by passingT[]orT[N]as the template argument,
            and the constructor from a raw pointer will install an appropriate array
            deleter. | 
| P0163R0 | shared_ptr::weak_type | The class shared_ptr<T>now has a member typeweak_typewhich isweak_ptr<T>. This
            allows generic code to name the corresponding weak pointer type without
            having to destructure the shared pointer type. | 
| P0030R1 | Three-dimensional hypotenuse | The three-dimensional hypotenuse hypot(x, y, z)is
            added as an additional set of overloads to<cmath>(but not
            to<math.h>and only to namespacestd). | 
| P0040R3 | Further uninitialized algorithms | Additional algorithms to create objects in uninitialized memory and to destroy objects. Separate versions for default- and value-initialization are included. | 
| N4510 | Incomplete type support for allocators | This change relaxes the requirements on allocators to have complete
            value types, and allows, for example, recursive structures like: struct X { std::vector<X> data; }; | 
| P0092R1, P0505R0 | Changes to <chrono> | Adds floor, ceiling, division and rounding for time points; makes most member functions constexpr. | 
| P0426R1 | Constexpr for char_traits | All specializations required for char_traitsnow have
            constexpr member functionslength,compare,findandassign, allowing string views
            to be more widely used in constant expressions. | 
| N4387 | Improving pairandtuple | This change makes the constructors of pairandtupleas explicit as the corresponding element type
            constructors. | 
| P0435R1, P0548R1 | Changes to common_type | Because it’s not a new standard if we didn’t make changes
            to common_type… | 
| Document | Summary | Examples, notes | 
|---|---|---|
| P0063R3 | C++ refers to C11 | The C++ standard now refers normatively to C11 (ISO/IEC 9899:2011) as
            “The C Standard”. Not only does ISO require that references to
            other international standards refer to the latest published version, and not
            to a historic version, but this also gives us access to aligned_alloc, which is useful for the improvements to our
            dynamic memory management. | 
| P0180R2 | Reserved namespaces | All top-level namespaces of the form stdX,
            whereXis a sequence of digits, are reserved. | 
| P0175R1 | C library synopses | A purely editorial change: all headers of the “C library” part of the standard library are now presented as complete synopses in the C++ standard document, rather than as just lists of names. This makes the changes in semantics from C easier to appreciate (e.g. additional overloads, overloads on language linkage). | 
| N4262 P0134R0 P0391R0 N4284 | Term “forwarding reference” Term “default member initializer” Term “templated entity” Term “contiguous iterator” | These changes have no normative impact, but they establish official terminology for concepts that have so far only emerged from the language rules. Having precise and well-known terms simplifies talking about C++ and simplifies the specification. | 
| P0346R1 | Change “random number generator” to “random bit generator” | Similarly, this change has no normative impact, but clarifies the
            design and intended use of this aspect of the <random>facilities. | 
The following papers were moved at committee meetings, but their contents are too specific to call out as separate features: N4258, N4268, N4277, N4285, P0031R0, P0074R0, P0270R3, P0283R2, P0296R2, P0503R0, P0509R1, P0516R0, P0517R0, P0558R1, P0599R1, P0612R0
The following papers contain issues that have been accepted as defect reports. CWG issues are handled by N4192, N4457, P0164R0, P0167R2, P0263R1, P0384R0, P0398R0, P0490R0, P0507R0, P0519R0, P0520R0, P0575R1, P0576R1, P0613R0, P0622R0. LWG issues are handled by N4245, N4366, N4383, N4525, P0165R0, P0165R1, P0165R2, P0165R2, P0165R3, P0165R4, P0304R1, P0397R0, P0610R0, P0625R0. Only specific issues may have been selected from each paper; the meeting minutes contain the details. The following separate papers resolve specific issues: N4089, N4261, P0033R1, P0136R1, P0250R3, P0418R2, P0513R0. The complete accumulation of accepted issues is published in the regularly updated CWG issues list and LWG issues list.
The following papers contain (not exclusively) wording changes that do not appear in the published International Standard, but that are considered defects in C++17: P0710R1, P0711R0, P0727R0, P0817R0, P0818R0, P0859R0, P0929R2, P0962R1.
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++17 and that are intended as defect reports are annotated with “DR” in the above change summary. Defect reports against C++17 that concern older (pre-C++17) content are not called out here specifically, nor are defects against C++14 whose resolutions are included in C++17. 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.
The next snippet illustrates the utility of template <auto>
      on the example of a class template which delegates a free function call to a
      member function bound to a class instance, and the member function is part of
      the delegate type.
The next snippet shows the utility of fold expressions in generic code.
The next snippet shows array support for shared pointers.