Benjamin Kosnik <bkoz@redhat.com>
Matt Austern <austern@google.com>
N2270=07-0130
2007-04-26
Incompatible changes in C++0x
This document collects the various source-incompatible changes and deprecation
suggestions that have been made for C++0x, and notes potential ABI trouble
spots. It is certainly not an exhaustive list, but it documents the changes that
may or will break code. It includes both core and library changes.
The committee has not yet made a formal decision to break the ABI, but most
committee members seem to believe that C++0x will force vendors to make
ABI-incompatible changes.
Existing source- and ABI-breaking changes
This section describes decisions we have already made for C++0x that may break
or change the meaning of valid C++03 source code.
Right angle brackets
The following code is valid in C++98/03 (because
">>" is a right-shift
operator) but invalid in C++0x (because the
">>" closes two templates:
template<typename T> struct X { };
template<int N> struct Y { };
X< Y< 1 >> 2 > > x;
New keywords and identifiers
The consequences of introducing new keywords are believed to be well understood,
and while care has been taken in choosing these keywords to minimize impact on
existing code (by choosing rarely-used identifiers), some C++98 code will be
invalidated by their addition.
New keywords include:
axiom,
char16_t,
char32_t,
constexpr,
concept,
concept_map,
decltype,
late_check,
requires,
static_assert. Pending proposals
for garbage collection, lambda, and threads suggest additional keywords not yet
voted into the standard.
New additions to namespace std
include the following, broken down by identifying proposal.
Rvalue-references:
identity, forward, unique_ptr
Type Traits:
integral_constant, true_type, false_type, is_void,
is_integral, is_floating_point, is_array, is_pointer, is_reference,
is_member_object_pointer, is_member_function_pointer, is_enum, is_union,
is_class, is_function, is_arithmetic, is_fundamental, is_member_pointer,
is_scalar, is_object, is_compound, is_const, is_volatile, remove_const,
remove_volatile, remove_cv, add_const, add_volatile, add_cv, remove_reference,
add_reference, remove_pointer, add_pointer, is_signed, is_unsigned, rank,
extent, remove_extent, remove_all_extents, is_pod, is_empty, is_polymorphic,
is_abstract, has_trivial_default_contructor, has_trivial_copy_constructor,
has_trivial_assign, has_trivial_destructor, has_nothrow_default_constructor,
has_nothrow_copy_constructor, has_nothrow_assign, has_virtual_destructor,
is_same, is_base_of, is_convertible, alignment_of, aligned_storage, decay,
enable_if, conditional
New Character types:
u16string, u32string
Least crazy:
next, prev, is_sorted_until, is_sorted,
is_heap
Random:
linear_congruential_engine, mersenne_twister_engine,
subtract_with_carry_engine, discard_block_engine, independent_bits_engine,
shuffle_order_engine, xor_combine_engine, minstd_rand0, minstd_rand, mt19937,
ranlux24_base, ranlux48_bse, ranlux24, ranlux48, knuth_b, random_device,
seed_seq, generate_cannonical, uniform_int_distribution,
uniform_real_distribution, bernoulli_distribution, binomial_distribution,
geometric_distribution, negative_binomial_distribution, poisson_distribution,
exponential_distribution, gamma_distribution, weibull_distribution,
extreme_value_distribution, normal_distribution, lognormal_distribution,
chi_squared_distribution, cauchy_distribution, fisher_f_distribution,
student_t_distribution, discrete_distribution,
piecewise_constant_distribution, general_pdf_distribution
TR1 + edits:
reference_wrapper, bad_weak_ptr, shared_ptr,
static_pointer_cast, dynamic_pointer_cast, const_pointer_cast, get_deleter,
weak_ptr, enable_shared_from_this, result_of, mem_fn, is_bind_expression,
is_placeholder, bind, placeholders, bad_function_call, function, tuple,
ignore, tuple_size, tuple_element, array, get, hash, unordered_set,
unordered_multiset, unordered_map, unordered_multimap, regex_constants,
regex_error, regex_traits, regex, wregex, sub_match, regex_match,
regex_search, regex_replace, regex_iterator, regex_token_iterator
C99:
isblank, fenv_t, fexcept_t, feclearexcept,
fegetexceptflag, fesetexceptflag, fetestexcept, fegetround, fesetround,
fegetenv, feholdexcept, fesetenv, feupdateenv, hexfloat, imaxdiv_t, imaxabs,
div, strtoimx, strtoumax, wcstoimax, wcstoumax, atanhl, cbrt, cbrtf, cbrtl,
copysign, copysignf, copysignl, erf, erff, erfl, erfc, erfcf, erfcl, exp2,
exp2f, exp2l, expm1, expm1f, expmil, fdim, fdimf, fdiml, fma, fmaf, fmal,
fmax, fmaxf, fmaxl, fmin, fminf, fminl, hypot, hypotf, hpotl, ilogb, ilogbf,
ilogbl, lgamma, lgammaf, lgammal, llrint, llrintf, llrintl llround, llroundf,
llroundl, logip, log1pf, log1pl, log2, log2f, log2l, logb, logbf, logbl,
lrint, lrintf, lrintl, lround, lroundf, lroundl, nan, nanf, nanl, nearbyint,
nearbyintf, nearbyintl, nextafter, nextafterf, nextafterl, nexttoward,
nexttowardf, nexttowardl, remainder, remainderf, remainderl, remquo, remquof,
remquol, rint, rintf, rintl, round, roundf, roundl, scalbln, scalblnf, salbln,
scalbn, scalbnf, scalbnl, tgamma, tgammf, tgamml, trunc, truncf, truncl,
signbit, fpclassify, isfinite, isinf, isnan, isnormal, isgreater,
istreaterequal, isless, islessequal, islessgreater, isunordered, int_fast8_t,
int_fast16_t, int_fast32_t, int_fast64_t, int_least8_t, int_least16_t,
int_least32_t, int_least64_t, intmax_t, intptr_t, uint_fast8_t, uint_fast16_t,
uint_fast32_t, uint_fast64_t, uint_least8_t, uint_least16_t, uint_least32_t,
uint_least64_t, uintmax_t, uintptr_t, snprintf, vsnprintf, vfscanf, vscanf,
vsscanf, lldiv_t, llabs, lldiv, atoll, strtoll, strtoull, strtof, strtold,
div, wcstof, wcstold, wcstoll, wcstoull, vfwscanf, vswscanf,
vwscanf
Diagnostic Enhancements:
system_error, error_code, error_category, posix_category, native_category,
hash_value, posix_errno,
address_family_not_supported,
address_in_use,
address_not_available, already_connected, argument_list_too_long,
argument_out_of_domain, bad_address, bad_file_descriptor,
bad_message, broken_pipe,
connection_aborted, connection_already_in_progress, connection_refused,
connection_reset, cross_device_link, destination_address_required,
device_or_resource_busy,
directory_not_empty,
executable_format_error, file_exists, file_too_large,
filename_too_long, function_not_supported, host_unreachable,
identifier_removed, illegal_byte_sequence, inappropriate_io_control_operation,
interrupted, invalid_argument, invalid_seek, io_error, is_a_directory,
message_size, network_down, network_reset, network_unreachable,
no_buffer_space, no_child_process, no_link, no_lock_available,
no_message_available, no_message, no_protocol_option, no_space_on_device,
no_stream_resources, no_such_device_or_address, no_such_device,
no_such_file_or_directory, no_such_process, not_a_directory, not_a_socket,
not_a_stream, not_connected, not_enough_memory, not_supported,
operation_canceled, operation_in_progress, operation_not_permitted,
operation_not_supported, operation_would_block, other, permission_denied,
protocol_error, protocol_not_supported, read_only_file_system,
resource_deadlock_would_occur, resource_unavailable_try_again,
result_out_of_range, stream_timeout, text_file_busy, timed_out,
too_many_files_open_in_system, too_many_files_open, too_many_links,
too_many_synbolic_link_levels, value_too_large, wrong_protocol_type
New macros include all from the POSIX header <errno.h> plus EOTHER, from
<fenv.h>, <cfloat>, <cinttypes>, <climits>,
<cmath>, <cstdarg>, <cstdbool>, and <cstdint>
Constant expressions
N2219
"Constant expressions in the Standard Library", changes the meaning of some
ill-behaved programs that use bitmask types in unintended ways. In C++03, for
example, ios_base::fmtflags is
defined to be an arbitrary bitmask type, as describe in 17.3.2.1.2.
Implementations are permitted to implement a bitmask type as an integer type, as
an enum, or as an std::bitset. On
an implementation that chooses to make
ios_base::fmtflags a
bitset, users could write
expressions like
std::cout.flags().count(), and on
an implementation that chooses to make
ios_base::fmtflags an integer, users could write expressions like
std::cout.setf(17). Programs that
do these things were never portable, but they compile and run without error on
at least some platforms. N2219 requires ios_base::fmtflags to be an enum,
breaking both of these pathological examples.
Concepts
Concepts have an unknown but potentially large impact on source compatibility,
largely because specifying the concepts in code is likely to prohibit some
pathological uses of standard library components that were never guaranteed to
work but that did happen to work on some implementations. Concept maps are
likely to affect mangling, and are thus likely to be a hot spot for ABI-breaking
changes. It is undetermined if the additional requirements for mangling can be
implemented so as to be compatible with existing ABIs for C++03.
Concepts also raise the question of container-like classes in the standard
library that do not meet the existing container requirements, such as
std::bitset,
std::vector<bool>,
std::unordered_set, and
std::unordered_map.
In principle we could change those classes to come into conformance, or change
the requirements to include a minimal container concept that all containers
share, or deprecate or remove those classes. Any of those options can affect
source compatibility.
Potential source- and ABI-breaking changes
This section describes proposed changes, not yet approved for C++0x, that might
also break or change the meaning of valid C++03 source code.
Container changes
N2217,
"Placement insert for containers," adds new insert overloads for containers. New
overloads can occasionally change which member function gets called. This is
probably not going to be an issue, however, because it is expected that the
revision of N2217 will give these member functions different names. As these are
non-virtual member function additions, it is believed to be ABI compatible.
N1771,
"Impact of the rvalue reference on the Standard Library," adds new member
functions for containers: constructors with a std::size_t parameter, and
resize with a std::size_t and value type parameter. New constructors may impact
existing conversion sequences, but are believed to be ABI compatible.
Allocator changes
N2257
proposes removing the allocator member functions
construct,
destroy, and
address, to make room for
emplace (as described in
N2217).
It calls for containers to use placement new, and explicit destructor calls,
instead. The proposal call for the removal of those member functions from both
std::allocator and from the allocator concept. This will break source
compatibility with C++03 code that calls those members directly, but is probably
not an ABI-breaking change. If users implement those members in their own
allocators and expect that the standard containers will call them, then this
change will make it impossible to do that. After a review of existing practice
in the GNU C++ library (libstdc++), (a) no such user code is known to exist
outside of tests cases, and (b) that code already isn't portable, since standard
containers aren't required to call those member functions.
Facets, locales, and iostreams
N2211
proposes enhancements to the time_get facet. It appears to be source-compatible
with C++03, but it may be ABI-breaking because it proposes new virtual member
functions.
N2186
proposes a number of small additions to iostream, including operator<< and
operator>> for long long,
access to the underlying file descriptor, and mutexes for iostream objects. All
of this appears to be source-compatible, but it is almost certainly ABI-breaking
and may be a change of behavior. Mutexes will change the sizes of objects, and
supporting long long will involve
adding new virtual member functions in I/O facets.
In addition, a coherent strategy for dealing with error handling across the
standard library has yet to be devised. Known issues exist with current
iostreams error handling and threads: thread cancellation and exception handling
issues may be incompatible, as currently defined. As major new functionality
(like atomics and threads) get integrated into the C++ library, exiting error
handling strategies may have to adapt. These changes may make C++0x code catch
or throw errors differently than C++03.
We have not yet decided on a policy for fixing other design mistakes in locale,
e.g. the messages facet.
Existing deprecated changes
The latest draft of C++0x has moved the following C++03 items to annex D,
deprecated.
-
std::bind1st,
std::binder1st,
std::bind2nd,
std::binder2nd (since
std::bind does everything they
do, but better)
-
The use of an operand of type
bool with the ++ operator
-
The use of the static keyword
when declaring objects in namespace scope.
-
Access declarations.
Potential deprecated changes
vector<bool>
N2204
suggests deprecating
vector<bool> and closing
problematic semantic loopholes. It isn't yet clear what it means to deprecate a
single specialization of a template, but a future revision of that paper may
clarify this important procedural question. Others have suggested removing the
specialization entirely, instead of just deprecating it; yet others suggest
keeping vector<bool> in the
library, documenting its behavior, and adding concept support.
Tuple and pair consolidation
It would be very nice for pair<int,
int> to be a POD, or rather, in Beman's new terminology, for it to be
a trivial type. Currently it fails to be a trivial type because it has a
user-defined default constructor. One option would be to fix that, i.e. to use
the new =default language feature
to remove the user-defined constructor. This would change behavior in a few
minor cases because of default initialization. The change is small enough that
it is probably acceptable, and we would probably have used this feature from the
beginning if it had been available in C++98. It is slightly worrying, however,
that the change would not manifest itself until run time.
We should almost certainly change
std::tuple's default constructor to
use =default, meaning that
tuple<T1,...,TN>
will be trivial iff
T1,...,TN
are all trivial. Since tuple isn't
part of C++03, we don't have to worry about compatibility.
If we do make this change in tuple
but not in pair, we should consider
deprecating pair. There is very
little reason, other than history, for the library to contain both
pair<T,U> and
tuple<T,U>. If we do
deprecate pair then we should
change all interfaces in the library that use it, including the associative
containers, to use tuple instead.
This will be a source-incompatible change, but it need not be ABI-breaking.
Others
Various people have suggested deprecating the following features:
-
std::auto_ptr (See
N1771)
-
std::valarray (On the grounds
that people who do serious array work in C++ tend to use Blitz, MTL, or some
other third-party library, and if
valarray is deprecated concept
support will not have to be retrofitted.)
-
std::raw_storage_iterator,
which, especially in light of exception safety, has outlived its usefulness.
-
std::mem_fun,
std::mem_fun_ref, and their
associated classes (Again, since std::mem_fn has all the same functionality
but is more convenient and uniform).
-
std::ptr_fun and its associated
classes
Potential removal candidates
-
The decay of narrow string literals to
char* (as opposed to
const char*) was deprecated in
C++03. There hasn't yet been a paper proposing removal for C++0x, but the
intention was always that it be removed in a future revision of the
standard. If we remove it in C++0x then we will, obviously, be breaking any
code that currently relies on it.
-
std::valarray
-
std::vector<bool>
There is no proposal to remove the deprecated iostream features from D.6 and
D.7.