Annex C (informative) Compatibility [diff]

C.4 C++ and ISO C++ 2014 [diff.cpp14]

This subclause lists the differences between C++ and ISO C++ 2014 (ISO/IEC 14882:2014, Programming Languages — C++), by the chapters of this document.

C.4.1 Clause [lex]: lexical conventions [diff.cpp14.lex]

[lex.phases]
Change: Removal of trigraph support as a required feature.
Rationale: Prevents accidental uses of trigraphs in non-raw string literals and comments.
Effect on original feature: Valid C++ 2014 code that uses trigraphs may not be valid or may have different semantics in this International Standard. Implementations may choose to translate trigraphs as specified in C++ 2014 if they appear outside of a raw string literal, as part of the implementation-defined mapping from physical source file characters to the basic source character set.

[lex.ppnumber]
Change: pp-number can contain p sign and P sign.
Rationale: Necessary to enable hexadecimal floating literals.
Effect on original feature: Valid C++ 2014 code may fail to compile or produce different results in this International Standard. Specifically, character sequences like 0p+0 and 0e1_­p+0 are three separate tokens each in C++ 2014, but one single token in this International Standard.

#define F(a) b ## a
int b0p = F(0p+0);  // ill-formed; equivalent to “int b0p = b0p + 0;” in C++ 2014

C.4.2 Clause [expr]: expressions [diff.cpp14.expr]

[expr.post.incr], [expr.pre.incr]
Change: Remove increment operator with bool operand.
Rationale: Obsolete feature with occasionally surprising semantics.
Effect on original feature: A valid C++ 2014 expression utilizing the increment operator on a bool lvalue is ill-formed in this International Standard. Note that this might occur when the lvalue has a type given by a template parameter.

[expr.new], [expr.delete]
Change: Dynamic allocation mechanism for over-aligned types.
Rationale: Simplify use of over-aligned types.
Effect on original feature: In C++ 2014 code that uses a new-expression to allocate an object with an over-aligned class type, where that class has no allocation functions of its own, ​::​operator new(std​::​size_­t) is used to allocate the memory. In this International Standard, ​::​operator new(std​::​size_­t, std​::​align_­val_­t) is used instead.

C.4.3 Clause [dcl.dcl]: declarations [diff.cpp14.dcl.dcl]

[dcl.stc]
Change: Removal of register storage-class-specifier.
Rationale: Enable repurposing of deprecated keyword in future revisions of this International Standard.
Effect on original feature: A valid C++ 2014 declaration utilizing the register storage-class-specifier is ill-formed in this International Standard. The specifier can simply be removed to retain the original meaning.

[dcl.spec.auto]
Change: auto deduction from braced-init-list.
Rationale: More intuitive deduction behavior.
Effect on original feature: Valid C++ 2014 code may fail to compile or may change meaning in this International Standard. For example:

auto x1{1};    // was std​::​initializer_­list<int>, now int
auto x2{1, 2}; // was std​::​initializer_­list<int>, now ill-formed

C.4.4 Clause [dcl.decl]: declarators [diff.cpp14.decl]

[dcl.fct]
Change: Make exception specifications be part of the type system.
Rationale: Improve type-safety.
Effect on original feature: Valid C++ 2014 code may fail to compile or change meaning in this International Standard:

void g1() noexcept;
void g2();
template<class T> int f(T *, T *);
int x = f(g1, g2);    // ill-formed; previously well-formed

[dcl.init.aggr]
Change: Definition of an aggregate is extended to apply to user-defined types with base classes.
Rationale: To increase convenience of aggregate initialization.
Effect on original feature: Valid C++ 2014 code may fail to compile or produce different results in this International Standard; initialization from an empty initializer list will perform aggregate initialization instead of invoking a default constructor for the affected types:

struct derived;
struct base {
  friend struct derived;
private:
  base();
};
struct derived : base {};

derived d1{};       // Error. The code was well-formed before.
derived d2;         // still OK

C.4.5 Clause [special]: special member functions [diff.cpp14.special]

[class.inhctor.init]
Change: Inheriting a constructor no longer injects a constructor into the derived class.
Rationale: Better interaction with other language features.
Effect on original feature: Valid C++ 2014 code that uses inheriting constructors may not be valid or may have different semantics. A using-declaration that names a constructor now makes the corresponding base class constructors visible to initializations of the derived class rather than declaring additional derived class constructors.

struct A {
  template<typename T> A(T, typename T::type = 0);
  A(int);
};
struct B : A {
  using A::A;
  B(int);
};
B b(42L); // now calls B(int), used to call B<long>(long),
          // which called A(int) due to substitution failure
          // in A<long>(long).

C.4.6 Clause [temp]: templates [diff.cpp14.temp]

[temp.deduct.type]
Change: Allowance to deduce from the type of a non-type template argument.
Rationale: In combination with the ability to declare non-type template arguments with placeholder types, allows partial specializations to decompose from the type deduced for the non-type template argument.
Effect on original feature: Valid C++ 2014 code may fail to compile or produce different results in this International Standard:

template <int N> struct A;
template <typename T, T N> int foo(A<N> *) = delete;
void foo(void *);
void bar(A<0> *p) {
  foo(p); // ill-formed; previously well-formed
}

C.4.7 Clause [except]: exception handling [diff.cpp14.except]

[except.spec]
Change: Remove dynamic exception specifications.
Rationale: Dynamic exception specifications were a deprecated feature that was complex and brittle in use. They interacted badly with the type system, which became a more significant issue in this International Standard where (non-dynamic) exception specifications are part of the function type.
Effect on original feature: A valid C++ 2014 function declaration, member function declaration, function pointer declaration, or function reference declaration, if it has a potentially throwing dynamic exception specification, will be rejected as ill-formed in this International Standard. Violating a non-throwing dynamic exception specification will call terminate rather than unexpected and might not perform stack unwinding prior to such a call.

C.4.8 Clause [library]: library introduction [diff.cpp14.library]

[namespace.future]
Change: New reserved namespaces.
Rationale: Reserve namespaces for future revisions of the standard library that might otherwise be incompatible with existing programs.
Effect on original feature: The global namespaces std followed by an arbitrary sequence of digits is reserved for future standardization. Valid C++ 2014 code that uses such a top-level namespace, e.g., std2, may be invalid in this International Standard.

C.4.9 Clause [utilities]: general utilities library [diff.cpp14.utilities]

[func.wrap]
Change: Constructors taking allocators removed.
Rationale: No implementation consensus.
Effect on original feature: Valid C++ 2014 code may fail to compile or may change meaning in this International Standard. Specifically, constructing a std​::​function with an allocator is ill-formed and uses-allocator construction will not pass an allocator to std​::​function constructors in this International Standard.

[util.smartptr.shared]
Change: Different constraint on conversions from unique_­ptr.
Rationale: Adding array support to shared_­ptr, via the syntax shared_­ptr<T[]> and shared_­ptr<T[N]>.
Effect on original feature: Valid C++ 2014code may fail to compile or may change meaning in this International Standard. For example:

#include <memory>
std::unique_ptr<int[]> arr(new int[1]);
std::shared_ptr<int> ptr(std::move(arr)); // error: int(*)[] is not compatible with int*

C.4.10 Clause [strings]: strings library [diff.cpp14.string]

[basic.string]
Change: Non-const .data() member added.
Rationale: The lack of a non-const .data() differed from the similar member of std​::​vector. This change regularizes behavior for this International Standard.
Effect on original feature: Overloaded functions which have differing code paths for char* and const char* arguments will execute differently when called with a non-const string's .data() member in this International Standard.

int f(char *) = delete;
int f(const char *);
string s;
int x = f(s.data()); // ill-formed; previously well-formed

C.4.11 Clause [containers]: containers library [diff.cpp14.containers]

[associative.reqmts]
Change: Requirements change:
Rationale: Increase portability, clarification of associative container requirements.
Effect on original feature: Valid C++ 2014 code that attempts to use associative containers having a comparison object with non-const function call operator may fail to compile in this International Standard:

#include <set>

struct compare
{
  bool operator()(int a, int b)
  {
    return a < b;
  }
};

int main() {
  const std::set<int, compare> s;
  s.find(0);
}

C.4.12 Annex [depr]: compatibility features [diff.cpp14.depr]


Change: The class templates auto_­ptr, unary_­function, and binary_­function, the function templates random_­shuffle, and the function templates (and their return types) ptr_­fun, mem_­fun, mem_­fun_­ref, bind1st, and bind2nd are not defined.
Rationale: Superseded by new features.
Effect on original feature: Valid C++ 2014 code that uses these class templates and function templates may fail to compile in this International Standard.


Change: Remove old iostreams members [depr.ios.members].
Rationale: Redundant feature for compatibility with pre-standard code has served its time.
Effect on original feature: A valid C++ 2014 program using these identifiers may be ill-formed in this International Standard.