Effect of operator<=> on the C++ Standard Library

Document Number: P0790R1
Date: 2018-08-06
Author: David Stone (davidmstone@google.com, david@doublewise.net)
Audience: LEWG, LWG

This paper lists (what are expected to be) non-controversial changes to the C++ standard library in response to P0515, which adds operator<=> to the language. This is expected to be non-controversial because it tries to match existing behavior as much as possible. As a result, all proposed additions are either strong_equality or strong_ordering, matching the existing comparison operators.

This document should contain a complete list of types or categories of types in C++.

Revision History

R1: A much broader version of this paper was presented to LEWG at a previous meeting. What remains in this paper is everything which the group did not find controversial and which probably does not require significant justification. All controversial aspects will be submitted in separate papers.

Backward Compatibility

The operator<=> proposal was written such that the "generated" operators are equivalent to source code rewrites – there is no actual operator== that a user could take the address of. Users are not allowed to form pointers to standard library member functions and are unable to form pointers to friend functions defined inline in the class. There are some cases where we do not specify how the operator was implemented, only that the expression a @ b is valid; these cases are not broken by such a change because users could not have depended on it, anyway. In general, we accept changes that overload existing functions, which also has the effect of breaking code which takes the address of a free function.

Types that are not proposed to get operator<=> in this paper

These types are not comparable now. This paper does not propose adding any new comparisons to any of these types.

Types from C that are not proposed to get operator<=> in this paper

Types that should get operator<=>, no change from current comparisons

These types are all currently comparable.

Types that will get their operator<=> from a conversion operator

These types will get operator<=> if possible without any changes, just like they already have whatever comparison operators their underlying type has.

This has the disadvantage that types which have a template comparison operator will not have their wrapper convertible. For instance, std::reference_wrapper<std::string> is not currently comparable. This does not affect bitset::reference, as it has a fixed conversion to bool, but it does affect the other three.

Types that wrap another type

This turned out to be much more complicated than expected and will require its own paper.

basic_string, basic_string_view, char_traits, and sub_match

Properly integrating operator<=> with these types requires more thought than this paper has room for, and thus will be discussed separately.

unique_ptr and shared_ptr

They contain state that is not observed in the comparison operators. Therefore, they will get their own paper.

valarray

Current comparison operators return a valarray<bool>, giving you the result for each pair (with undefined behavior for differently-sized valarray arguments). It might make sense to provide some sort of function that returns valarray<comparison_category>, but that should not be named operator<=>. This paper does not suggest adding operator<=> to valarray.

Types that have no comparisons now but are being proposed to get operator<=> in another paper

This paper does not propose changing any of the following types -- they are here only for completeness.

nullptr_t

Already supports strong_equality in the working draft. I will be writing a separate paper proposing strong_ordering.

Not Updating Concepts That Provide Comparisons

This category includes things like BinaryPredicate and Compare. This is addressed in a separate paper.

Not Updating Concepts That Require Comparisons

This includes things like LessThanComparable and EqualityComparable. This is addressed in a separate paper.

Miscellaneous

All operator<=> should be constexpr and noexcept where possible, following the lead of the language feature and allowing = default as an implementation strategy for some types.

When we list a result type as "unspecified" it is unspecified whether it has operator<=>. There are not any unspecified result types for which we currently guarantee any comparison operators are present, so there is no extra work to do here.