Annex C (informative) Compatibility [diff]

C.5 C++ and ISO C++ 2017 [diff.cpp17]

C.5.5 [class]: classes [diff.cpp17.class]

Affected subclauses: [class.ctor] and [class.conv.fct]
Change: The class name can no longer be used parenthesized immediately after an explicit decl-specifier in a constructor declaration.
The conversion-function-id can no longer be used parenthesized immediately after an explicit decl-specifier in a conversion function declaration.

Rationale: Necessary for new functionality.

Effect on original feature: Valid C++ 2017 code may fail to compile in this International Standard.
For example:
struct S {
  explicit (S)(const S&);       // ill-formed; previously well-formed
  explicit (operator int)();    // ill-formed; previously well-formed
  explicit(true) (S)(int);      // OK
};
Affected subclauses: [class.ctor] and [class.dtor]
Change: A simple-template-id is no longer valid as the declarator-id of a constructor or destructor.

Rationale: Remove potentially error-prone option for redundancy.

Effect on original feature: Valid C++ 2017 code may fail to compile in this International Standard.
For example:
template<class T>
struct A {
  A<T>();           // error: simple-template-id not allowed for constructor
  A(int);           // OK, injected-class-name used
  ~A<T>();          // error: simple-template-id not allowed for destructor
};
Affected subclause: [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.
Function and catch-clause parameters can be thrown using move constructors.

Rationale: Side effect of making it easier to write more efficient code that takes advantage of moves.

Effect on original feature: Valid C++ 2017 code may fail to compile or have different semantics in this International Standard.
For example:
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
}