General topics | ||||||||||||||||
Flow control | ||||||||||||||||
Conditional execution statements | ||||||||||||||||
Iteration statements (loops) | ||||||||||||||||
Jump statements | ||||||||||||||||
Functions | ||||||||||||||||
Function declaration | ||||||||||||||||
Lambda function expression | ||||||||||||||||
inline specifier | ||||||||||||||||
Dynamic exception specifications(until C++17*) | ||||||||||||||||
noexcept specifier(C++11) | ||||||||||||||||
Exceptions | ||||||||||||||||
Namespaces | ||||||||||||||||
Types | ||||||||||||||||
Specifiers | ||||||||||||||||
| ||||||||||||||||
Storage duration specifiers | ||||||||||||||||
Initialization | ||||||||||||||||
Expressions | ||||||||||||||||
Alternative representations | ||||||||||||||||
Literals | ||||||||||||||||
Boolean -Integer -Floating-point | ||||||||||||||||
Character -String -nullptr(C++11) | ||||||||||||||||
User-defined(C++11) | ||||||||||||||||
Utilities | ||||||||||||||||
Attributes(C++11) | ||||||||||||||||
Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
Type alias declaration(C++11) | ||||||||||||||||
Casts | ||||||||||||||||
Memory allocation | ||||||||||||||||
Classes | ||||||||||||||||
Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
Special member functions | ||||||||||||||||
Templates | ||||||||||||||||
Miscellaneous | ||||||||||||||||
General | |||||||||||||||||||||||||||||||||||||||||||||||||||
Literals | |||||||||||||||||||||||||||||||||||||||||||||||||||
Operators | |||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||
Conversions | |||||||||||||||||||||||||||||||||||||||||||||||||||
Comparison operator functions can be explicitly defaulted to request the compiler to generate the corresponding default comparison for a class.
Contents |
Adefaulted comparison operator function is a non-template comparison operator function (i.e.<=>
,==
,!=
,<
,>
,<=
, or>=
) satisfying all following conditions:
C
.C
or in a context whereC
iscomplete.C
, where theimplicit object parameter (if any) is considered to be the first parameter.Such a comparison operator function is termed adefaulted comparison operator function for classC
.
struct X{bool operator==(const X&)const=default;// OKbool operator==(const X&)=default;// Error: the implicit object// parameter type is X&bool operator==(this X, X)=default;// OK}; struct Y{friendbool operator==(Y, Y)=default;// OKfriendbool operator==(Y,const Y&)=default;// Error: different parameter types}; bool operator==(const Y&,const Y&)=default;// Error: not a friend of Y
Name lookups and access checks in the implicit definition of a comparison operator function are performed from a context equivalent to its function body. A definition of a comparison operator function as defaulted that appears in a class must be the first declaration of that function.
Given a classC
, a subobject list is formed by the following subjects in order:
C
, in declaration order.C
, in declaration order.For any objectx of typeC
, in the following descriptions:
struct S{}; struct T: S{int arr[2][2];} t; // The subobject list for “t” consists of the following 5 subobjects in order:// (S)t → t[0][0] → t[0][1] → t[1][0] → t[1][1]
Anoperator<=> for a class type can be defined as defaulted with any return type.
There are three comparison category types:
Type | Equivalent values are.. | Incomparable values are.. |
---|---|---|
std::strong_ordering | indistinguishable | not allowed |
std::weak_ordering | distinguishable | not allowed |
std::partial_ordering | distinguishable | allowed |
Thesynthesized three-way comparison of typeT
between glvaluesa andb of the same type is defined as follows:
T
usingstatic_cast
, the synthesized comparison isstatic_cast<T>(a<=> b).T
is not a comparison category type.T
isstd::strong_ordering, the synthesized comparison isa== b? std::strong_ordering::equal:a< b? std::strong_ordering::less: std::strong_ordering::greater
T
isstd::weak_ordering, the synthesized comparison isa== b? std::weak_ordering::equivalent:a< b? std::weak_ordering::less: std::weak_ordering::greater
T
isstd::partial_ordering), the synthesized comparison isa== b? std::partial_ordering::equivalent:a< b? std::partial_ordering::less:b< a? std::partial_ordering::greater: std::partial_ordering::unordered
If the declared return type of a defaulted three-way comparison operator function (operator<=>) for a class typeC
isauto, the return type is deduced from the return types of the three-way comparisons between the corresponding subobjects of an objectx of typeC
.
For each subobjectx_i in the(expanded) subobject list forx:
R_i
, ifR_i
is not a comparison category type, the defaultedoperator<=> is defined as deleted.If the defaultedoperator<=> is not defined as deleted, its return type is deduced asstd::common_comparison_category_t<R_1, R_2, ..., R_n>.
If the declared return type of the defaultedoperator<=> is notauto, it cannot contain anyplaceholder type (e.g.decltype(auto)).
If there is a subobjectx_i in the (expanded) subobject list forx such that thesynthesized three-way comparison of the declared return type betweenx_i andx_i is not defined, the defaultedoperator<=> is defined as deleted.
Letx andy be the parameters of a defaultedoperator<=>, denote each subobject in the (expanded) subobject list forx andy asx_i andy_i respectively. The default three-way comparison betweenx andy is performed by comparing corresponding subobjectsx_i andy_i with increasingi order.
LetR
be the (possibly-deduced) return type, the comparison result betweenx_i andy_i is the result of the synthesized three-way comparison of typeR
betweenx_i andy_i.
#include <compare>#include <iostream>#include <set> struct Point{int x;int y;auto operator<=>(const Point&)const=default;/* non-comparison functions */}; int main(){ Point pt1{1,1}, pt2{1,2};std::set<Point> s;// OK s.insert(pt1);// OK // two-way comparison operator functions are not required to be explicitly defined:// operator== is implicitly declared (see below)// the overload resolutions of other candidates will select rewritten candidatesstd::cout<<std::boolalpha<<(pt1== pt2)<<' '// false<<(pt1!= pt2)<<' '// true<<(pt1< pt2)<<' '// true<<(pt1<= pt2)<<' '// true<<(pt1> pt2)<<' '// false<<(pt1>= pt2)<<' ';// false}
Anoperator== for a class type can be defined as defaulted with return typebool.
Given a classC
and an objectx of typeC
, if there is a subobjectx_i in the (expanded) subobject list forx such that the overload resolution forx_i== x_i does not result in a usable candidate, the defaultedoperator== is defined as deleted.
Letx andy be the parameters of a defaultedoperator==, denote each subobject in the (expanded) subobject list forx andy asx_i andy_i respectively. The default equality comparison betweenx andy is performed by comparing corresponding subobjectsx_i andy_i with increasingi order.
The comparison result betweenx_i andy_i is the result ofx_i== y_i.
#include <iostream> struct Point{int x;int y;bool operator==(const Point&)const=default;/* non-comparison functions */}; int main(){ Point pt1{3,5}, pt2{2,5};std::cout<<std::boolalpha<<(pt1!= pt2)<<'\n'// true<<(pt1== pt1)<<'\n';// true struct[[maybe_unused]]{int x{}, y{};} p, q;// if (p == q) {} // Error: operator== is not defined}
If a classC
does not explicitly declare any member or friend namedoperator==, an==
operator function is declared implicitly for eachoperator<=> defined as defaulted. Each implicity-declaredoperator== have the same access andfunction definition and in the sameclass scope as the respective defaultedoperator<=>, with the following changes:
template<typename T>struct X{friendconstexprstd::partial_ordering operator<=>(X, X) requires(sizeof(T)!=1)=default;// implicitly declares: friend constexpr bool operator==(X, X)// requires (sizeof(T) != 1) = default; [[nodiscard]]virtualstd::strong_ordering operator<=>(const X&)const=default;// implicitly declares: [[nodiscard]] virtual bool// operator==(const X&) const = default;};
A secondary comparison operator function (!=
,<
,>
,<=
, or>=
) for a class type can be defined as defaulted with return typebool.
Let@
be one of the five secondary comparison operators, for each defaultedoperator@ with parametersx andy, up to two overloads resolutions are performed (not considering the defaultedoperator@ as a candidate) to determine whether it is defined as deleted.
If isx @ y cannot be implicitly converted tobool, the defaultedoperator@ is defined as deleted.
If the defaultedoperator@ is not defined as deleted, it yieldsx @ y.
struct HasNoRelational{}; struct C{friend HasNoRelational operator<=>(const C&,const C&);bool operator<(const C&)const=default;// OK, function is defaulted};
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 2539 | C++20 | the synthesized three-way comparison would choose static_cast even if the explicit conversion is not available | does not choose static_cast in this case |
CWG 2546 | C++20 | the defaulted secondaryoperator@ was not defined as deleted if the overload resolution of x @ y selects a non-usable rewritten candidate | defined as deleted in this case |
CWG 2547 | C++20 | it was unclear whether comparison operator functions for non-classes can be defaulted | they cannot be defaulted |
CWG 2568 | C++20 | the implicit definition of comparison operator functions might violate member access rules | access checks are performed from a context equivalent to their function bodies |