C++11 includes new smart pointer classes: shared_ptr and the recently-added unique_ptr. Both are compatible with other Standard Library components, so you can safely store these smart pointers in standard containers and manipulate them with standard algorithms.
Noun. (computing) A change in one part of a software system that potentially causes other components to fail; occurs most often in shared libraries of code used by multiple applications. Not possible to fix old entries without a breaking change, so remap old to new in import lib.
C++11 allowed lambda functions to deduce the return type based on the type of the expression given to the return statement. C++14 provides this ability to all functions. It also extends these facilities to lambda functions, allowing return type deduction for functions that are not of the form return expression; .
Most of C++14 new features will not break source compatibility with current C++11 standard. The introduction of generic lambdas, e.g., allowing lambda function parameters to be declared with the auto type specifier, will not break compatibility with C++11 lambdas.
The FDIS has a section for incompatibilities, at appendix C.2
"C++ and ISO C++ 2003".
Summary, paraphrasing the FDIS here, to make it (better) suitable as a SO answer. I added some examples of my own to illustrate the differences.
There are a few library-related incompatibilities where I don't exactly know the implications of, so I leave those for others to elaborate on.
#define u8 "abc"
const char *s = u8"def"; // Previously "abcdef", now "def"
#define _x "there"
"hello"_x // now a user-defined-string-literal. Previously, expanded _x .
New keywords: alignas, alignof, char16_t, char32_t, constexpr, decltype, noexcept, nullptr, static_assert, and thread_local
Certain integer literals larger than can be represented by long could change from an unsigned integer type to signed long long.
Valid C++ 2003 code that uses integer division rounds the result toward 0 or toward negative infinity, whereas C++0x always rounds the result toward 0.
(admittedly not really a compatibility problem for most people).
Valid C++ 2003 code that uses the keyword
auto
as a storage class specifier may be invalid in C++0x.
Narrowing conversions cause incompatibilities with C++03. For example, the following code is valid in C++ 2003 but invalid in this International Standard because double to int is a narrowing conversion:
int x[] = { 2.0 };
Implicitly-declared special member functions are defined as deleted when the implicit definition would have been ill-formed.
A valid C++ 2003 program that uses one of these special member functions in a context where the definition is not required (e.g., in an expresion that is not potentially evaluated) becomes ill-formed.
Example by me:
struct A { private: A(); };
struct B : A { };
int main() { sizeof B(); /* valid in C++03, invalid in C++0x */ }
Such sizeof tricks have been used by some SFINAE, and needs to be changed now :)
User-declared destructors have an implicit exception specification.
Example by me:
struct A {
~A() { throw "foo"; }
};
int main() { try { A a; } catch(...) { } }
This code calls terminate
in C++0x, but does not in C++03. Because the implicit exception specification of A::~A
in C++0x is noexcept(true)
.
A valid C++ 2003 declaration containing
export
is ill-formed in C++0x.
A valid C++ 2003 expression containing
>
followed immediately by another>
may now be treated as closing two templates.
In C++03, >>
would always be the shift-operator token.
Allow dependent calls of functions with internal linkage.
Example by me:
static void f(int) { }
void f(long) { }
template<typename T>
void g(T t) { f(t); }
int main() { g(0); }
In C++03, this calls f(long)
, but in C++0x, this calls f(int)
. It should be noted that in both C++03 and C++0x, the following calls f(B)
(the instantiation context still only considers extern linkage declarations).
struct B { };
struct A : B { };
template<typename T>
void g(T t) { f(t); }
static void f(A) { }
void f(B) { }
int main() { A a; g(a); }
The better matching f(A)
is not taken, because it does not have external linkage.
Valid C++ 2003 code that uses any identifiers added to the C++ standard library of C++0x may fail to compile or produce different results in This International Standard.
Valid C++ 2003 code that
#includes
headers with names of new C++0x standard library headers may be invalid in this International Standard.
Valid C++ 2003 code that has been compiled expecting swap to be in
<algorithm>
may have to instead include<utility>
The global namespace
posix
is now reserved for standardization.
Valid C++ 2003 code that defines
override
,final
,carries_dependency
, ornoreturn
as macros is invalid in C++0x.
The meaning of the auto keyword changed.
Breaking change?
Well, for one thing, if you used decltype
, constexpr
, nullptr
, etc. as identifiers then you may be in trouble...
Some core incompatibilities that are not covered by the incompatibilities section:
C++0x treats the injected class name as a template, if the name is passed as an argument to a template template parameter, and as a type if it is passed to a template type parameter.
Valid C++03 code may behave differently if it relies on the injected class name to be always a type in these scenarios. Example code taken from my clang PR
template<template<typename> class X>
struct M { };
template<template<typename> class X>
void g(int = 0); // #1
template<typename T>
void g(long = 0); // #2
template<typename T>
struct A {
void f() {
g<A>(); /* is ambiguous in C++0x */
g<A>(1); /* should choose #1 in C++0x */
}
};
void h() {
A<int> a;
a.f();
}
In C++03, the code calls the second g
both times.
C++0x makes some names that were dependent in C++03 to be now non-dependent. And requires name lookup for non-dependent qualified names that refer to members of the current class template to be repeated at instantiation, and requires verification that these names lookup the same way as done at the template definition context.
Valid C++03 code that depends on the dominance rule may now not compile anymore because of this change.
Example:
struct B { void f(); };
template<typename T>
struct A : virtual B { void f(); };
template<typename T>
struct C : virtual B, A<T> {
void g() { this->f(); }
};
int main() { C<int> c; c.g(); }
This valid C++03 code that calls A<int>::f
is not valid in C++0x, because name lookup when instantiating will find A<int>::f
as opposed to B::f
, causing a conflict with the at-definition lookup.
At this point, it is not clear whether that is a defect in the FDIS. The committee is aware of this and will evaluate the situation.
A using declaration where the last part is the same as the identifier in the last part of the qualifier in the qualified name denoting a base class, that using declaration now names the constructor, instead of members with that name.
Example:
struct A { protected: int B; };
typedef A B;
struct C : B {
// inheriting constructor, instead of bringing A::B into scope
using B::B;
};
int main() { C c; c.B = 0; }
The above example code is well-formed in C++03, but ill-formed in C++0x, as A::B
is still inaccessible in main
.
Stream extraction failure is treated differently.
#include <sstream>
#include <cassert>
int main()
{
std::stringstream ss;
ss << '!';
int x = -1;
assert(!(ss >> x)); // C++03 and C++11
assert(x == -1); // C++03
assert(x == 0); // C++11
}
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3246.html#23
[C++03: 22.2.2.1.2/11]:
The result of stage 2 processing can be one of
- A sequence of chars has been accumulated in stage 2 that is converted (according to the rules of
scanf
) to a value of the type ofval
. This value is stored inval
andios_base::goodbit
is stored inerr
.- The sequence of chars accumulated in stage 2 would have caused
scanf
to report an input failure.ios_base::failbit
is assigned toerr
. [ed: Nothing is stored inval
.]
[C++11: 22.4.2.1.2/3]:
[..] The numeric value to be stored can be one of:
- zero, if the conversion function fails to convert the entire field.
ios_base::failbit
is assigned toerr
.- the most positive representable value, if the field represents a value too large positive to be represented in
val
.ios_base::failbit
is assigned toerr
.- the most negative representable value or zero for an unsigned integer type, if the field represents a value too large negative to be represented in
val
.ios_base::failbit
is assigned toerr
.- the converted value, otherwise.
The resultant numeric value is stored in
val
.
GCC 4.8 correctly outputs for C++11:
Assertion `x == -1' failed
GCC 4.5-4.8 all output for C++03 the following, which would appear to be a bug:
Assertion `x == -1' failed
Visual C++ 2008 Express correctly outputs for C++03:
Assertion failed: x == 0
Visual C++ 2012 Express incorrectly outputs for C++11, which would appear to be a status-of-implementation issue:
Assertion failed: x == 0
How is the introduction of explicit conversion operators a breaking change? The old version will still just be as "valid" as before.
Yes, the change from operator void*() const
to explicit operator bool() const
will be a breaking change, but only if it is used in a way that is wrong in and out of itself. Conforming code won't be broken.
Now, another breaking change is the banning of narrowing conversions during aggregate initialization:
int a[] = { 1.0 }; // error
Edit: Just rememberer, std::identity<T>
will be removed in C++0x (see the note). It's a convenience struct to make types dependent. Since the struct really doesn't do much, this should fix it:
template<class T>
struct identity{
typedef T type;
};
There are numerous changes to the containers library that allow more efficient code but silently break backwards compatibility for a few corner cases.
Consider, for example, std::vector
, default construction, C++0x, and breaking changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With