928 lines
36 KiB
Markdown
928 lines
36 KiB
Markdown
[diff.cpp17]
|
||
|
||
# Annex C (informative) Compatibility [[diff]](./#diff)
|
||
|
||
## C.3 C++ and ISO C++ 2017 [diff.cpp17]
|
||
|
||
### [C.3.1](#general) General [[diff.cpp17.general]](diff.cpp17.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L834)
|
||
|
||
Subclause [diff.cpp17] lists the differences between C++ and
|
||
ISO C++ 2017,
|
||
in addition to those listed above,
|
||
by the chapters of this document[.](#general-1.sentence-1)
|
||
|
||
### [C.3.2](#lex) [[lex]](lex "5 Lexical conventions"): lexical conventions [[diff.cpp17.lex]](diff.cpp17.lex)
|
||
|
||
[1](#lex-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L843)
|
||
|
||
**Affected subclauses:** [[lex.pptoken]](lex.pptoken), [[module.unit]](module.unit), [[module.import]](module.import), [[cpp.pre]](cpp.pre), [[cpp.module]](cpp.module), and [[cpp.import]](cpp.import)
|
||
|
||
|
||
**Change:** New identifiers with special meaning[.](#lex-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Required for new features[.](#lex-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Logical lines beginning withmodule or import may
|
||
be interpreted differently
|
||
in this revision of C++[.](#lex-1.sentence-3)
|
||
|
||
[*Example [1](#lex-example-1)*: class module {};module m1; // was variable declaration; now [*module-declaration*](module.unit#nt:module-declaration "10.1 Module units and purviews [module.unit]")module *m2; // variable declarationclass import {};import j1; // was variable declaration; now [*module-import-declaration*](module.import#nt:module-import-declaration "10.3 Import declaration [module.import]")::import j2; // variable declaration â *end example*]
|
||
|
||
[2](#lex-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L865)
|
||
|
||
**Affected subclause:** [[lex.header]](lex.header)
|
||
|
||
|
||
**Change:** [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") tokens are formed in more contexts[.](#lex-2.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Required for new features[.](#lex-2.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** When the identifier import is followed by a < character,
|
||
a [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") token may be formed[.](#lex-2.sentence-3)
|
||
|
||
[*Example [2](#lex-example-2)*: template<typename> class import {};import<int> f(); // ill-formed; previously well-formed::import<int> g(); // OK â *end example*]
|
||
|
||
[3](#lex-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L882)
|
||
|
||
**Affected subclause:** [[lex.key]](lex.key)
|
||
|
||
|
||
**Change:** New keywords[.](#lex-3.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Required for new features[.](#lex-3.sentence-2)
|
||
|
||
- [(3.1)](#lex-3.1)
|
||
|
||
The char8_t keyword is added to differentiate
|
||
the types of ordinary and UTF-8 literals ([[lex.string]](lex.string "5.13.5 String literals"))[.](#lex-3.1.sentence-1)
|
||
|
||
- [(3.2)](#lex-3.2)
|
||
|
||
The concept keyword is
|
||
added to enable the definition of concepts ([[temp.concept]](temp.concept "13.7.9 Concept definitions"))[.](#lex-3.2.sentence-1)
|
||
|
||
- [(3.3)](#lex-3.3)
|
||
|
||
The consteval keyword is added to
|
||
declare immediate functions ([[dcl.constexpr]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers"))[.](#lex-3.3.sentence-1)
|
||
|
||
- [(3.4)](#lex-3.4)
|
||
|
||
The constinit keyword is added to
|
||
prevent unintended dynamic initialization ([[dcl.constinit]](dcl.constinit "9.2.7 The constinit specifier"))[.](#lex-3.4.sentence-1)
|
||
|
||
- [(3.5)](#lex-3.5)
|
||
|
||
The co_await, co_yield, and co_return keywords are added
|
||
to enable the definition of coroutines ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions"))[.](#lex-3.5.sentence-1)
|
||
|
||
- [(3.6)](#lex-3.6)
|
||
|
||
The requires keyword is added
|
||
to introduce constraints through a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble"))
|
||
or a [*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") ([[expr.prim.req]](expr.prim.req "7.5.8 Requires expressions"))[.](#lex-3.6.sentence-1)
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code usingchar8_t,concept,consteval,constinit,co_await, co_yield, co_return,
|
||
or requires as an identifier is not valid in this revision of C++[.](#lex-3.sentence-3)
|
||
|
||
[4](#lex-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L919)
|
||
|
||
**Affected subclause:** [[lex.operators]](lex.operators)
|
||
|
||
|
||
**Change:** New operator <=>[.](#lex-4.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Necessary for new functionality[.](#lex-4.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code that contains a <= token
|
||
immediately followed by a > token
|
||
may be ill-formed or have different semantics in this revision of C++[.](#lex-4.sentence-3)
|
||
|
||
[*Example [3](#lex-example-3)*: namespace N {struct X {}; bool operator<=(X, X); template<bool(X, X)> struct Y {};
|
||
Y<operator<=> y; // ill-formed; previously well-formed} â *end example*]
|
||
|
||
[5](#lex-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L939)
|
||
|
||
**Affected subclause:** [[lex.literal]](lex.literal)
|
||
|
||
|
||
**Change:** Type of UTF-8 string and character literals[.](#lex-5.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Required for new features[.](#lex-5.sentence-2)
|
||
|
||
The changed types enable function overloading, template specialization, and
|
||
type deduction to distinguish ordinary and UTF-8 string and character literals[.](#lex-5.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code that depends on
|
||
UTF-8 string literals having type âarray of const charâ and
|
||
UTF-8 character literals having type âcharâ
|
||
is not valid in this revision of C++[.](#lex-5.sentence-4)
|
||
|
||
[*Example [4](#lex-example-4)*: const auto *u8s = u8"text"; // u8s previously deduced as const char*; now deduced as const char8_t*const char *ps = u8s; // ill-formed; previously well-formedauto u8c = u8'c'; // u8c previously deduced as char; now deduced as char8_tchar *pc = &u8c; // ill-formed; previously well-formed std::string s = u8"text"; // ill-formed; previously well-formedvoid f(const char *s);
|
||
f(u8"text"); // ill-formed; previously well-formedtemplate<typename> struct ct;template<> struct ct<char> {using type = char;};
|
||
ct<decltype(u8'c')>::type x; // ill-formed; previously well-formed. â *end example*]
|
||
|
||
### [C.3.3](#basic) [[basic]](basic "6 Basics"): basics [[diff.cpp17.basic]](diff.cpp17.basic)
|
||
|
||
[1](#basic-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L975)
|
||
|
||
**Affected subclause:** [[basic.life]](basic.life)
|
||
|
||
|
||
**Change:** A pseudo-destructor call ends the lifetime of
|
||
the object to which it is applied[.](#basic-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Increase consistency of the language model[.](#basic-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid ISO C++ 2017 code may be ill-formed or
|
||
have undefined behavior in this revision of C++[.](#basic-1.sentence-3)
|
||
|
||
[*Example [1](#basic-example-1)*: int f() {int a = 123; using T = int;
|
||
a.~T(); return a; // undefined behavior; previously returned 123} â *end example*]
|
||
|
||
[2](#basic-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L995)
|
||
|
||
**Affected subclause:** [[intro.races]](intro.races)
|
||
|
||
|
||
**Change:** Except for the initial release operation,
|
||
a release sequence consists solely of atomic read-modify-write operations[.](#basic-2.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Removal of rarely used and confusing feature[.](#basic-2.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** If a memory_order_release atomic store is followed
|
||
by a memory_order_relaxed store to the same variable by the same thread,
|
||
then reading the latter value with a memory_order_acquire load
|
||
no longer provides any âhappens beforeâ guarantees,
|
||
even in the absence of intervening stores by another thread[.](#basic-2.sentence-3)
|
||
|
||
### [C.3.4](#expr) [[expr]](expr "7 Expressions"): expressions [[diff.cpp17.expr]](diff.cpp17.expr)
|
||
|
||
[1](#expr-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1010)
|
||
|
||
**Affected subclause:** [[expr.prim.lambda.capture]](expr.prim.lambda.capture)
|
||
|
||
|
||
**Change:** Implicit lambda capture may capture additional entities[.](#expr-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Rule simplification, necessary to resolve interactions with constexpr if[.](#expr-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Lambdas with a [*capture-default*](expr.prim.lambda.capture#nt:capture-default "7.5.6.3 Captures [expr.prim.lambda.capture]") may capture local entities
|
||
that were not captured in C++ 2017
|
||
if those entities are only referenced in contexts
|
||
that do not result in an odr-use[.](#expr-1.sentence-3)
|
||
|
||
### [C.3.5](#dcl.dcl) [[dcl]](dcl "9 Declarations"): declarations [[diff.cpp17.dcl.dcl]](diff.cpp17.dcl.dcl)
|
||
|
||
[1](#dcl.dcl-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1024)
|
||
|
||
**Affected subclause:** [[dcl.typedef]](dcl.typedef)
|
||
|
||
|
||
**Change:** Unnamed classes with a typedef name for linkage purposes
|
||
can contain only C-compatible constructs[.](#dcl.dcl-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Necessary for implementability[.](#dcl.dcl-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code may be ill-formed in this revision of C++[.](#dcl.dcl-1.sentence-3)
|
||
|
||
[*Example [1](#dcl.dcl-example-1)*: typedef struct {void f() {} // ill-formed; previously well-formed} S; â *end example*]
|
||
|
||
[2](#dcl.dcl-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1040)
|
||
|
||
**Affected subclause:** [[dcl.fct.default]](dcl.fct.default)
|
||
|
||
|
||
**Change:** A function cannot have different default arguments
|
||
in different translation units[.](#dcl.dcl-2.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Required for modules support[.](#dcl.dcl-2.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code may be ill-formed in this revision of C++,
|
||
with no diagnostic required[.](#dcl.dcl-2.sentence-3)
|
||
|
||
[*Example [2](#dcl.dcl-example-2)*: // Translation unit 1int f(int a = 42);int g() { return f(); }// Translation unit 2int f(int a = 76) { return a; } // ill-formed, no diagnostic required; previously well-formedint g();int main() { return g(); } // used to return 42 â *end example*]
|
||
|
||
[3](#dcl.dcl-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1062)
|
||
|
||
**Affected subclause:** [[dcl.init.aggr]](dcl.init.aggr)
|
||
|
||
|
||
**Change:** A class that has user-declared constructors is never an aggregate[.](#dcl.dcl-3.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Remove potentially error-prone aggregate initialization
|
||
which may apply notwithstanding the declared constructors of a class[.](#dcl.dcl-3.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code that aggregate-initializes
|
||
a type with a user-declared constructor
|
||
may be ill-formed or have different semantics
|
||
in this revision of C++[.](#dcl.dcl-3.sentence-3)
|
||
|
||
[*Example [3](#dcl.dcl-example-3)*: struct A { // not an aggregate; previously an aggregate A() = delete;};
|
||
|
||
struct B { // not an aggregate; previously an aggregate B() = default; int i = 0;};
|
||
|
||
struct C { // not an aggregate; previously an aggregate C(C&&) = default; int a, b;};
|
||
|
||
A a{}; // ill-formed; previously well-formed B b = {1}; // ill-formed; previously well-formedauto* c = new C{2, 3}; // ill-formed; previously well-formedstruct Y;
|
||
|
||
struct X {operator Y();};
|
||
|
||
struct Y { // not an aggregate; previously an aggregate Y(const Y&) = default;
|
||
X x;};
|
||
|
||
Y y{X{}}; // copy constructor call; previously aggregate-initialization â *end example*]
|
||
|
||
[4](#dcl.dcl-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1108)
|
||
|
||
**Affected subclause:** [[dcl.init.list]](dcl.init.list)
|
||
|
||
|
||
**Change:** Boolean conversion from a pointer or pointer-to-member type
|
||
is now a narrowing conversion[.](#dcl.dcl-4.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Catches bugs[.](#dcl.dcl-4.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code may fail to compile
|
||
in this revision of C++[.](#dcl.dcl-4.sentence-3)
|
||
|
||
[*Example [4](#dcl.dcl-example-4)*: bool y[] = { "bc" }; // ill-formed; previously well-formed â *end example*]
|
||
|
||
### [C.3.6](#class) [[class]](class "11 Classes"): classes [[diff.cpp17.class]](diff.cpp17.class)
|
||
|
||
[1](#class-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1125)
|
||
|
||
**Affected subclauses:** [[class.ctor]](class.ctor) and [[class.conv.fct]](class.conv.fct)
|
||
|
||
|
||
**Change:** The class name can no longer be used parenthesized
|
||
immediately after an explicit [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") in a constructor declaration[.](#class-1.sentence-1)
|
||
|
||
The [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") can no longer be used parenthesized
|
||
immediately after an explicit [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") in a conversion function declaration[.](#class-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Necessary for new functionality[.](#class-1.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code may fail to compile
|
||
in this revision of C++[.](#class-1.sentence-4)
|
||
|
||
[*Example [1](#class-example-1)*: struct S {explicit (S)(const S&); // ill-formed; previously well-formedexplicit (operator int)(); // ill-formed; previously well-formedexplicit(true) (S)(int); // OK}; â *end example*]
|
||
|
||
[2](#class-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1148)
|
||
|
||
**Affected subclauses:** [[class.ctor]](class.ctor) and [[class.dtor]](class.dtor)
|
||
|
||
|
||
**Change:** A [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") is no longer valid as the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") of a constructor or destructor[.](#class-2.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Remove potentially error-prone option for redundancy[.](#class-2.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code may fail to compile
|
||
in this revision of C++[.](#class-2.sentence-3)
|
||
|
||
[*Example [2](#class-example-2)*: template<class T>struct A { A<T>(); // error: [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") not allowed for constructor A(int); // OK, injected-class-name used~A<T>(); // error: [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") not allowed for destructor}; â *end example*]
|
||
|
||
[3](#class-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1168)
|
||
|
||
**Affected subclause:** [[class.copy.elision]](class.copy.elision)
|
||
|
||
|
||
**Change:** A function returning an implicitly movable entity
|
||
may invoke a constructor taking an rvalue reference to a type
|
||
different from that of the returned expression[.](#class-3.sentence-1)
|
||
|
||
Function and catch-clause parameters can be thrown using move constructors[.](#class-3.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Side effect of making it easier to write
|
||
more efficient code that takes advantage of moves[.](#class-3.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code may fail to compile or have different semantics
|
||
in this revision of C++[.](#class-3.sentence-4)
|
||
|
||
[*Example [3](#class-example-3)*: struct base { base();
|
||
base(base const &);private: base(base &&);};
|
||
|
||
struct derived : base {};
|
||
|
||
base f(base b) {throw b; // error: base(base &&) is private derived d; return d; // error: base(base &&) is private}struct S { S(const char *s) : m(s) { } S(const S&) = default;
|
||
S(S&& other) : m(other.m) { other.m = nullptr; }const char * m;};
|
||
|
||
S consume(S&& s) { return s; }void g() { S s("text");
|
||
consume(static_cast<S&&>(s)); char c = *s.m; // undefined behavior; previously ok} â *end example*]
|
||
|
||
### [C.3.7](#over) [[over]](over "12 Overloading"): overloading [[diff.cpp17.over]](diff.cpp17.over)
|
||
|
||
[1](#over-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1216)
|
||
|
||
**Affected subclause:** [[over.match.oper]](over.match.oper)
|
||
|
||
|
||
**Change:** Equality and inequality expressions can now find
|
||
reversed and rewritten candidates[.](#over-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Improve consistency of equality with three-way comparison
|
||
and make it easier to write the full complement of equality operations[.](#over-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** For certain pairs of types where one is convertible to the other,
|
||
equality or inequality expressions between an object of one type
|
||
and an object of the other type invoke a different operator[.](#over-1.sentence-3)
|
||
|
||
Also, for certain types, equality or inequality expressions
|
||
between two objects of that type become ambiguous[.](#over-1.sentence-4)
|
||
|
||
[*Example [1](#over-example-1)*: struct A {operator int() const;};
|
||
|
||
bool operator==(A, int); // #1// #2 is built-in candidate: bool operator==(int, int);// #3 is built-in candidate: bool operator!=(int, int);int check(A x, A y) {return (x == y) + // ill-formed; previously well-formed(10 == x) + // calls #1, previously selected #2(10 != x); // calls #1, previously selected #3} â *end example*]
|
||
|
||
[2](#over-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1247)
|
||
|
||
**Affected subclause:** [[over.match.oper]](over.match.oper)
|
||
|
||
|
||
**Change:** Overload resolution may change for equality operators ([[expr.eq]](expr.eq "7.6.10 Equality operators"))[.](#over-2.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Support calling operator== with reversed order of arguments[.](#over-2.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code that uses equality operators with conversion functions
|
||
may be ill-formed or have different semantics in this revision of C++[.](#over-2.sentence-3)
|
||
|
||
[*Example [2](#over-example-2)*: struct A {operator int() const { return 10; }};
|
||
|
||
bool operator==(A, int); // #1// #2 is built-in candidate: bool operator==(int, int);bool b = 10 == A(); // calls #1 with reversed order of arguments; previously selected #2struct B {bool operator==(const B&); // member function with no cv-qualifier};
|
||
B b1;bool eq = (b1 == b1); // ambiguous; previously well-formed â *end example*]
|
||
|
||
### [C.3.8](#temp) [[temp]](temp "13 Templates"): templates [[diff.cpp17.temp]](diff.cpp17.temp)
|
||
|
||
[1](#temp-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1275)
|
||
|
||
**Affected subclause:** [[temp.names]](temp.names)
|
||
|
||
|
||
**Change:** An [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") that is followed by a < and for which name lookup
|
||
finds nothing or finds a function
|
||
will be treated as a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") in order to potentially cause argument-dependent lookup to be performed[.](#temp-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** It was problematic to call a function template
|
||
with an explicit template argument list
|
||
via argument-dependent lookup
|
||
because of the need to have a template with the same name
|
||
visible via normal lookup[.](#temp-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Previously valid code that uses a function name
|
||
as the left operand of a < operator
|
||
would become ill-formed[.](#temp-1.sentence-3)
|
||
|
||
[*Example [1](#temp-example-1)*: struct A {};bool operator<(void (*fp)(), A);void f() {}int main() { A a;
|
||
f < a; // ill-formed; previously well-formed(f) < a; // still well-formed} â *end example*]
|
||
|
||
### [C.3.9](#except) [[except]](except "14 Exception handling"): exception handling [[diff.cpp17.except]](diff.cpp17.except)
|
||
|
||
[1](#except-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1308)
|
||
|
||
**Affected subclause:** [[except.spec]](except.spec)
|
||
|
||
|
||
**Change:** Remove throw() exception specification[.](#except-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Removal of obsolete feature that has been replaced by noexcept[.](#except-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C++ 2017 function declaration, member function declaration, function
|
||
pointer declaration, or function reference declaration that uses throw() for its exception specification will be rejected as ill-formed in this
|
||
revision of C++[.](#except-1.sentence-3)
|
||
|
||
It should simply be replaced with noexcept for no
|
||
change of meaning since C++ 2017[.](#except-1.sentence-4)
|
||
|
||
[*Note [1](#except-note-1)*:
|
||
|
||
There is no way to write a function declaration
|
||
that is non-throwing in this revision of C++
|
||
and is also non-throwing in C++ 2003
|
||
except by using the preprocessor to generate
|
||
a different token sequence in each case[.](#except-1.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
### [C.3.10](#library) [[library]](library "16 Library introduction"): library introduction [[diff.cpp17.library]](diff.cpp17.library)
|
||
|
||
[1](#library-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1329)
|
||
|
||
**Affected subclause:** [[headers]](headers)
|
||
|
||
|
||
**Change:** New headers[.](#library-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** New functionality[.](#library-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** The following C++ headers are new:[<barrier>](barrier.syn#header:%3cbarrier%3e "32.9.3.2 Header <barrier> synopsis [barrier.syn]"),[<bit>](bit.general#header:%3cbit%3e "22.11.1 General [bit.general]"),[<charconv>](charconv.syn#header:%3ccharconv%3e "28.2.1 Header <charconv> synopsis [charconv.syn]"),[<compare>](compare.syn#header:%3ccompare%3e "17.12.1 Header <compare> synopsis [compare.syn]"),[<concepts>](concepts.syn#header:%3cconcepts%3e "18.3 Header <concepts> synopsis [concepts.syn]"),[<coroutine>](coroutine.syn#header:%3ccoroutine%3e "17.13.2 Header <coroutine> synopsis [coroutine.syn]"),[<format>](format.formatter.spec#header:%3cformat%3e "28.5.6.4 Formatter specializations [format.formatter.spec]"),[<latch>](latch.syn#header:%3clatch%3e "32.9.2.2 Header <latch> synopsis [latch.syn]"),[<numbers>](numbers.syn#header:%3cnumbers%3e "29.8.1 Header <numbers> synopsis [numbers.syn]"),[<ranges>](ranges.syn#header:%3cranges%3e "25.2 Header <ranges> synopsis [ranges.syn]"),[<semaphore>](semaphore.syn#header:%3csemaphore%3e "32.8.2 Header <semaphore> synopsis [semaphore.syn]"),[<source_location>](source.location.syn#header:%3csource_location%3e "17.8.1 Header <source_location> synopsis [source.location.syn]"),[<span>](span.syn#header:%3cspan%3e "23.7.2.1 Header <span> synopsis [span.syn]"),[<stop_token>](thread.stoptoken.syn#header:%3cstop_token%3e "32.3.2 Header <stop_token> synopsis [thread.stoptoken.syn]"),[<syncstream>](syncstream.syn#header:%3csyncstream%3e "31.11.1 Header <syncstream> synopsis [syncstream.syn]"), and[<version>](version.syn#header:%3cversion%3e "17.3.2 Header <version> synopsis [version.syn]")[.](#library-1.sentence-3)
|
||
|
||
Valid C++ 2017 code that #includes headers with these names may be
|
||
invalid in this revision of C++[.](#library-1.sentence-4)
|
||
|
||
[2](#library-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1355)
|
||
|
||
**Affected subclause:** [[headers]](headers)
|
||
|
||
|
||
**Change:** Remove vacuous C++ header files[.](#library-2.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** The empty headers implied a false requirement to achieve C compatibility with the C++ headers[.](#library-2.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C++ 2017 program that #includes any of the following headers may fail to compile:<ccomplex>,<ciso646>,<cstdalign>,<cstdbool>, and<ctgmath>[.](#library-2.sentence-3)
|
||
|
||
To retain the same behavior:
|
||
|
||
- [(2.1)](#library-2.1)
|
||
|
||
a #include of <ccomplex> can be replaced by
|
||
a #include of [<complex>](complex.syn#header:%3ccomplex%3e "29.4.2 Header <complex> synopsis [complex.syn]"),
|
||
|
||
- [(2.2)](#library-2.2)
|
||
|
||
a #include of <ctgmath> can be replaced by
|
||
a #include of [<cmath>](cmath.syn#header:%3ccmath%3e "29.7.1 Header <cmath> synopsis [cmath.syn]") and
|
||
a #include of [<complex>](complex.syn#header:%3ccomplex%3e "29.4.2 Header <complex> synopsis [complex.syn]"),
|
||
and
|
||
|
||
- [(2.3)](#library-2.3)
|
||
|
||
a #include of<ciso646>,<cstdalign>, or<cstdbool> can simply be removed[.](#library-2.sentence-4)
|
||
|
||
### [C.3.11](#containers) [[containers]](containers "23 Containers library"): containers library [[diff.cpp17.containers]](diff.cpp17.containers)
|
||
|
||
[1](#containers-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1387)
|
||
|
||
**Affected subclauses:** [[forward.list]](forward.list) and [[list]](list)
|
||
|
||
|
||
**Change:** Return types of remove, remove_if, and unique changed from void to container::size_type[.](#containers-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Improve efficiency and convenience of finding number of removed elements[.](#containers-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Code that depends on the return types might have different semantics in this revision of C++[.](#containers-1.sentence-3)
|
||
|
||
Translation units compiled against this version of C++ may be incompatible with
|
||
translation units compiled against C++ 2017, either failing to link or having undefined behavior[.](#containers-1.sentence-4)
|
||
|
||
### [C.3.12](#iterators) [[iterators]](iterators "24 Iterators library"): iterators library [[diff.cpp17.iterators]](diff.cpp17.iterators)
|
||
|
||
[1](#iterators-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1400)
|
||
|
||
**Affected subclause:** [[iterator.traits]](iterator.traits)
|
||
|
||
|
||
**Change:** The specialization of iterator_traits for void* and
|
||
for function pointer types no longer contains any nested typedefs[.](#iterators-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Corrects an issue misidentifying pointer types that are not incrementable
|
||
as iterator types[.](#iterators-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C++ 2017 program that relies on the presence of the typedefs
|
||
may fail to compile, or have different behavior[.](#iterators-1.sentence-3)
|
||
|
||
### [C.3.13](#alg.reqs) [[algorithms]](algorithms "26 Algorithms library"): algorithms library [[diff.cpp17.alg.reqs]](diff.cpp17.alg.reqs)
|
||
|
||
[1](#alg.reqs-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1413)
|
||
|
||
**Affected subclause:** [[algorithms.requirements]](algorithms.requirements)
|
||
|
||
|
||
**Change:** The number and order of deducible template parameters for algorithm declarations
|
||
is now unspecified, instead of being as-declared[.](#alg.reqs-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Increase implementor freedom and allow some function templates
|
||
to be implemented as function objects with templated call operators[.](#alg.reqs-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C++ 2017 program that passes explicit template arguments to
|
||
algorithms not explicitly specified to allow such in this version of C++
|
||
may fail to compile or have undefined behavior[.](#alg.reqs-1.sentence-3)
|
||
|
||
### [C.3.14](#input.output) [[input.output]](input.output "31 Input/output library"): input/output library [[diff.cpp17.input.output]](diff.cpp17.input.output)
|
||
|
||
[1](#input.output-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1427)
|
||
|
||
**Affected subclause:** [[istream.extractors]](istream.extractors)
|
||
|
||
|
||
**Change:** Character array extraction only takes array types[.](#input.output-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Increase safety via preventing buffer overflow at compile time[.](#input.output-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code may fail to compile in this revision of C++[.](#input.output-1.sentence-3)
|
||
|
||
[*Example [1](#input.output-example-1)*: auto p = new char[100];char q[100];
|
||
std::cin >> std::setw(20) >> p; // ill-formed; previously well-formed std::cin >> std::setw(20) >> q; // OK â *end example*]
|
||
|
||
[2](#input.output-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1443)
|
||
|
||
**Affected subclause:** [[ostream.inserters.character]](ostream.inserters.character)
|
||
|
||
|
||
**Change:** Overload resolution for ostream inserters used with UTF-8 literals[.](#input.output-2.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Required for new features[.](#input.output-2.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code that passes UTF-8 literals tobasic_ostream<char, ...>::operator<< orbasic_ostream<wchar_t, ...>::operator<< is now ill-formed[.](#input.output-2.sentence-3)
|
||
|
||
[*Example [2](#input.output-example-2)*: std::cout << u8"text"; // previously called operator<<(const char*) and printed a string;// now ill-formed std::cout << u8'X'; // previously called operator<<(char) and printed a character;// now ill-formed â *end example*]
|
||
|
||
[3](#input.output-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1462)
|
||
|
||
**Affected subclause:** [[ostream.inserters.character]](ostream.inserters.character)
|
||
|
||
|
||
**Change:** Overload resolution for ostream inserters
|
||
used with wchar_t, char16_t, or char32_t types[.](#input.output-3.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Removal of surprising behavior[.](#input.output-3.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code that passeswchar_t, char16_t, or char32_t characters or strings
|
||
to basic_ostream<char, ...>::operator<< or
|
||
that passes char16_t or char32_t characters or strings
|
||
to basic_ostream<wchar_t, ...>::operator<< is now ill-formed[.](#input.output-3.sentence-3)
|
||
|
||
[*Example [3](#input.output-example-3)*: std::cout << u"text"; // previously formatted the string as a pointer value;// now ill-formed std::cout << u'X'; // previously formatted the character as an integer value;// now ill-formed â *end example*]
|
||
|
||
[4](#input.output-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1483)
|
||
|
||
**Affected subclause:** [[fs.class.path]](fs.class.path)
|
||
|
||
|
||
**Change:** Return type of filesystem path format observer member functions[.](#input.output-4.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** Required for new features[.](#input.output-4.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** Valid C++ 2017 code that depends on the u8string() andgeneric_u8string() member functions of std::filesystem::path returning std::string is not valid in this revision of C++[.](#input.output-4.sentence-3)
|
||
|
||
[*Example [4](#input.output-example-4)*: std::filesystem::path p;
|
||
std::string s1 = p.u8string(); // ill-formed; previously well-formed std::string s2 = p.generic_u8string(); // ill-formed; previously well-formed â *end example*]
|
||
|
||
### [C.3.15](#depr) [[depr]](depr "Annex D (normative) Compatibility features"): compatibility features [[diff.cpp17.depr]](diff.cpp17.depr)
|
||
|
||
[1](#depr-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1503)
|
||
|
||
**Change:** Remove uncaught_exception[.](#depr-1.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** The function did not have a clear specification when multiple exceptions were
|
||
active, and has been superseded by uncaught_exceptions[.](#depr-1.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C++ 2017 program that calls std::uncaught_exception may fail
|
||
to compile[.](#depr-1.sentence-3)
|
||
|
||
It can be revised to use std::uncaught_exceptions instead,
|
||
for clear and portable semantics[.](#depr-1.sentence-4)
|
||
|
||
[2](#depr-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1514)
|
||
|
||
**Change:** Remove support for adaptable function API[.](#depr-2.sentence-1)
|
||
|
||
**Rationale:** The deprecated support relied on a limited convention that could not be
|
||
extended to support the general case or new language features[.](#depr-2.sentence-2)
|
||
|
||
It has been
|
||
superseded by direct language support with decltype, and by thestd::bind and std::not_fn function templates[.](#depr-2.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C++ 2017 program that relies on the presence of result_type,argument_type, first_argument_type, orsecond_argument_type in a standard library class may fail to compile[.](#depr-2.sentence-4)
|
||
|
||
A
|
||
valid C++ 2017 program that calls not1 or not2, or uses the
|
||
class templates unary_negate or binary_negate, may fail to
|
||
compile[.](#depr-2.sentence-5)
|
||
|
||
[3](#depr-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1530)
|
||
|
||
**Change:** Remove redundant members from std::allocator[.](#depr-3.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** std::allocator was overspecified, encouraging direct usage in user containers
|
||
rather than relying on std::allocator_traits, leading to poor containers[.](#depr-3.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C++ 2017 program that directly makes use of the pointer,const_pointer, reference, const_reference,rebind, address, construct, destroy, ormax_size members of std::allocator, or that directly callsallocate with an additional hint argument, may fail to compile[.](#depr-3.sentence-3)
|
||
|
||
[4](#depr-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1543)
|
||
|
||
**Change:** Remove raw_storage_iterator[.](#depr-4.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** The iterator encouraged use of potentially-throwing algorithms, but did
|
||
not return the number of elements successfully constructed,
|
||
as would be necessary to destroy them[.](#depr-4.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C++ 2017 program that uses this iterator class may fail to compile[.](#depr-4.sentence-3)
|
||
|
||
[5](#depr-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1553)
|
||
|
||
**Change:** Remove temporary buffers API[.](#depr-5.sentence-1)
|
||
|
||
**Rationale:** The temporary buffer facility was intended to provide an efficient optimization
|
||
for small memory requests, but there is little evidence this was achieved in
|
||
practice, while requiring the user to provide their own exception-safe wrappers
|
||
to guard use of the facility in many cases[.](#depr-5.sentence-2)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C++ 2017 program that calls get_temporary_buffer orreturn_temporary_buffer may fail to compile[.](#depr-5.sentence-3)
|
||
|
||
[6](#depr-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1565)
|
||
|
||
**Change:** Remove shared_ptr::unique[.](#depr-6.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** The result of a call to this member function is not reliable in the presence of
|
||
multiple threads and weak pointers[.](#depr-6.sentence-2)
|
||
|
||
The member function use_count is
|
||
similarly unreliable, but has a clearer contract in such cases, and remains
|
||
available for well-defined use in single-threaded cases[.](#depr-6.sentence-3)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C++ 2017 program that calls unique on a shared_ptr object may fail to compile[.](#depr-6.sentence-4)
|
||
|
||
[7](#depr-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L1576)
|
||
|
||
**Affected subclause:** [[depr.meta.types]](depr.meta.types)
|
||
|
||
|
||
**Change:** Remove deprecated type traits[.](#depr-7.sentence-1)
|
||
|
||
|
||
|
||
|
||
**Rationale:** The traits had unreliable or awkward interfaces[.](#depr-7.sentence-2)
|
||
|
||
The is_literal_type trait provided no way to detect which subset of constructors and member
|
||
functions of a type were declared constexpr[.](#depr-7.sentence-3)
|
||
|
||
The result_of trait had a surprising syntax that did not directly support function types[.](#depr-7.sentence-4)
|
||
|
||
It has been superseded by the invoke_result trait[.](#depr-7.sentence-5)
|
||
|
||
|
||
|
||
|
||
**Effect on original feature:** A valid C++ 2017 program that relies on the is_literal_type orresult_of type traits, on the is_literal_type_v variable template,
|
||
or on the result_of_t alias template may fail to compile[.](#depr-7.sentence-6)
|