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.

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:

Potential removal candidates


There is no proposal to remove the deprecated iostream features from D.6 and D.7.