Compares the arguments.
Operator name  Syntax  Overloadable  Prototype examples (for class T ) 


As member function  As free (namespace) function  
equal to  a == b  Yes  bool T::operator ==(const T2 &b) const;  bool operator ==(const T &a, const T2 &b); 
not equal to  a != b  Yes  bool T::operator !=(const T2 &b) const;  bool operator !=(const T &a, const T2 &b); 
less than  a < b  Yes  bool T::operator <(const T2 &b) const;  bool operator <(const T &a, const T2 &b); 
greater than  a > b  Yes  bool T::operator >(const T2 &b) const;  bool operator >(const T &a, const T2 &b); 
less than or equal to  a <= b  Yes  bool T::operator <=(const T2 &b) const;  bool operator <=(const T &a, const T2 &b); 
greater than or equal to  a >= b  Yes  bool T::operator >=(const T2 &b) const;  bool operator >=(const T &a, const T2 &b); 
threeway comparison (C++20)  a <=> b  Yes  /*R*/ T::operator <=>(const T2 &b) const;  /*R*/ operator <=>(const T &a, const T2 &b); 
Notes

The twoway comparison operator expressions have the form.
lhs < rhs  (1)  
lhs > rhs  (2)  
lhs <= rhs  (3)  
lhs >= rhs  (4)  
lhs == rhs  (5)  
lhs != rhs  (6) 
true
if lhs is less than rhs, false
otherwise.true
if lhs is greater than rhs, false
otherwise.true
if lhs is less than or equal to rhs, false
otherwise.true
if lhs is greater than or equal to rhs, false
otherwise.true
if lhs is equal to rhs, false
otherwise.true
if lhs is not equal to rhs, false
otherwise.In all cases, for the builtin operators, lhs and rhs must have either.
after the application of the lvaluetorvalue, arraytopointer and functiontopointer standard conversions. The comparison is deprecated if both operands have array type prior to the application of these conversions. (since C++20).
In any case, the result is a bool
prvalue.
If the operands have arithmetic or enumeration type (scoped or unscoped), usual arithmetic conversions are performed on both operands following the rules for arithmetic operators. The values are compared after conversions:
#include <iostream> int main() { std::cout << std::boolalpha; int n = 1; int n2 = 1; std::cout << " 1 == 1? " << (n == n2) << '\n' << "Comparing two signed values:\n" << " 1 < 1? " << (n < n2) << '\n' << " 1 > 1? " << (n > n2) << '\n'; unsigned int u = 1; std::cout << "Comparing signed and unsigned:\n" << " 1 < 1? " << (n < u) << '\n' << " 1 > 1? " << (n > u) << '\n'; static_assert(sizeof(unsigned char) < sizeof(int), "Can't compare signed and smaller unsigned properly"); unsigned char uc = 1; std::cout << "Comparing signed and smaller unsigned:\n" << " 1 < 1? " << (n < uc) << '\n' << " 1 > 1? " << (n > uc) << '\n'; }
Output:
1 == 1? false Comparing two signed values: 1 < 1? true 1 > 1? false Comparing signed and unsigned: 1 < 1? false 1 > 1? true Comparing signed and smaller unsigned: 1 < 1? true 1 > 1? false
Comparison operators can be used to compare two pointers.
Only equality operators (operator==
and operator!=
) can be used to compare the following pointer pairs:
 (since C++11) 
First, pointer conversions (pointer to member conversions if the arguments are pointers to members), function pointer conversions, (since C++17) and qualification conversions are applied to both operands to obtain the composite pointer type, as follows.
1) If both operands are null pointer constants, the composite pointer type is std::nullptr_t  (since C++11) 
void
, and T
, where T
is an object type or void
, void
", where cv12 is the union of cv1 and cv2 4) If the types of the operands are P1
, a pointer to (possibly cvqualified) T1
, and P2
, a pointer to (possibly cvqualified) T2
, T1
is the same as T2
or is a base class of T2
, then the composite pointer type is the cvcombined type of P1
and P2
. Otherwise, if T2
is a base class of T1
, then the composite pointer type is the cvcombined type of P2
and P1
. 5) If the types of the operands are MP1
, pointer to member of T1
of type (possibly cvqualified) U1
, and MP2
, pointer to member of T2
of type (possibly cvqualified) U2
, T1
is the same as or derived from T2
, then the composite pointer type is the cvcombined type of MP1
and MP2
. Otherwise, if T2
is derived from T1
, then the composite pointer type is the cvcombined type of MP2
and MP1
. P1
and P2
are multilevel mixed pointer and pointer to member types with the same number of levels that only differ by cvqualifications at any of the levels, the composite pointer type is the cvcombined type of P1
and P2
.In the definition above, cvcombined type of two pointer types P1
and P2
is a type P3
that has the same number of levels and type at every level as P1
, except that cvqualifications at every level are set as follows:
P1
and P2
at that levelP1
's or P2
's cvqualification at the same level, then const
is added to every level between the top level and this one.For example, the composite pointer type of void*
and const int*
is const void*
. The composite pointer type of int**
and const int**
is const int* const*
. Note that until resolution of CWG1512, int**
and const int**
could not be compared.
In addition to the above, the composite pointer type between pointer to function and pointer to noexcept function (as long as the function type is the same) is pointer to function.  (since C++17) 
Note that this implies that any pointer can be compared with void*
.
The result of comparing two pointers to objects (after conversions) is defined as follows:
&obj+1
compares greater than &obj
.The result of equality comparison of two pointers (after conversions) is defined as follows:
reinterpret_cast
, etc)The result of comparing two pointers to members (after conversions) is defined as follows:
C1
and the other refers to a member of a different class C2
, where neither is a base class of the other, the result is unspecified. struct A {}; struct B : A { int x; }; struct C : A { int x; }; int A::*bx = (int(A::*)) &B::x; int A::*cx = (int(A::*)) &C::x; bool b1 = (bx == cx); // unspecified
struct B { int f(); }; struct L : B {}; struct R : B {}; struct D : L, R {}; int (B::*pb)() = &B::f; int (L::*pl)() = pb; int (R::*pr)() = pb; int (D::*pdl)() = pl; int (D::*pdr)() = pr; bool x = (pdl == pdr); // false bool y = (pb == pl); // true
If a pointer p
compare equal to pointer q
, p<=q
and p>=q
both yield true
and p<q
and p>q
both yield false
.
If a pointer p
compares greater than a pointer q
, then p>=q
, p>q
, q<=p
, and q<p
all yield true
and p<=q
, p<q
, q>=p
, and q>p
all yield false
.
If two pointers are not specified to compare greater or compare equal, the result of the comparison is unspecified. An unspecified result may be nondeterministic, and need not be consistent even for multiple evaluations of the same expression with the same operands in the same execution of the program:
int x, y; bool f(int* p, int* q) { return p < q; } assert(f(&x, &y) == f(&x, &y)); // may fire in a conforming implementation
In overload resolution against userdefined operators, for every pair of promoted arithmetic types L
and R
, including enumeration types, the following function signatures participate in overload resolution:
bool operator<(L, R);  
bool operator>(L, R);  
bool operator<=(L, R);  
bool operator>=(L, R);  
bool operator==(L, R);  
bool operator!=(L, R); 
For every type P
which is either pointer to object or pointer to function, the following function signatures participate in overload resolution:
bool operator<(P, P);  
bool operator>(P, P);  
bool operator<=(P, P);  
bool operator>=(P, P);  
bool operator==(P, P);  
bool operator!=(P, P); 
For every type MP
that is a pointer to member object or pointer to member function or std::nullptr_t
, the following function signatures participate in overload resolution:
bool operator==(MP, MP);  
bool operator!=(MP, MP); 
#include <iostream> struct Foo { int n1; int n2; }; union Union { int n; double d; }; int main() { std::cout << std::boolalpha; char a[4] = "abc"; char* p1 = &a[1]; char* p2 = &a[2]; std::cout << "Pointers to array elements:\n" << "p1 == p2? " << (p1 == p2) << '\n' << "p1 < p2? " << (p1 < p2) << '\n'; Foo f; int* p3 = &f.n1; int* p4 = &f.n2; std::cout << "Pointers to members of a class:\n" << "p3 == p4? " << (p3 == p4) << '\n' << "p3 < p4? " << (p3 < p4) << '\n'; Union u; int* p5 = &u.n; double* p6 = &u.d; std::cout << "Pointers to members of a union:\n" << "p5 == (void*)p6? " << (p5 == (void*)p6) << '\n' << "p5 < (void*)p6? " << (p5 < (void*)p6) << '\n'; }
Output:
Pointers to array elements: p1 == p2? false p1 < p2? true Pointers to members of a class: p3 == p4? false p3 < p4? true Pointers to members of a union: p5 == (void*)p6? true p5 < (void*)p6? false
Because these operators group lefttoright, the expression a<b<c
is parsed (a<b)<c
, and not a<(b<c)
or (a<b)&&(b<c)
.
#include <iostream> int main() { int a = 3, b = 2, c = 1; std::cout << std::boolalpha << ( a < b < c ) << '\n' // true; maybe warning << ( ( a < b ) < c ) << '\n' // true << ( a < ( b < c ) ) << '\n' // false << ( ( a < b ) && ( b < c ) ) << '\n'; // false }
A common requirement for userdefined operator< is strict weak ordering. In particular, this is required by the standard algorithms and containers that work with Compare types: std::sort
, std::max_element
, std::map
, etc.
Although the results of comparing pointers of random origin (e.g. not all pointing to members of the same array) is unspecified, many implementations provide strict total ordering of pointers, e.g. if they are implemented as addresses within continuous virtual address space. Those implementations that do not (e.g. where not all bits of the pointer are part of a memory address and have to be ignored for comparison, or an additional calculation is required or otherwise pointer and integer is not a 1 to 1 relationship), provide a specialization of std::less
for pointers that has that guarantee. This makes it possible to use all pointers of random origin as keys in standard associative containers such as std::set
or std::map
.
For the types that are both EqualityComparable and LessThanComparable, the C++ standard library makes a distinction between equality, which is the value of the expression a == b
and equivalence, which is the value of the expression !(a < b) && !(b < a)
.
Comparison between pointers and null pointer constants was removed by the resolution of CWG issue 583 included in N3624.
void f(char* p) { if (p > 0) { /*...*/ } // Error with N3624, compiled before N3624 if (p > nullptr) { /*...*/ } // Error with N3624, compiled before N3624 } int main() {}
Threeway comparisonThe threeway comparison operator expressions have the form.
The expression returns an object such that.
If one of the operands is of type If both operands have arithmetic types, or if one operand has unscoped enumeration type and the other has integral type, the usual arithmetic conversions are applied to the operands, and then.
If both operands have the same enumeration type If at least one of the operands is a pointer or pointertomember, arraytopointer conversions, derivedtobase pointer conversions, function pointer conversions, and qualification conversions are applied as necessary to convert both operands to the same pointer type, and the resulting pointer type is an object pointer type,
Otherwise, the program is illformed. In overload resolution against userdefined operators, for pointer or enumeration type
Where Example#include <compare> #include <iostream> int main() { double foo = 0.0; double bar = 0.0; auto res = foo <=> bar; if (res < 0) std::cout << "0 is less than 0"; else if (res > 0) std::cout << "0 is greater than 0"; else if (res == 0) std::cout << "0 and 0 are equal"; else std::cout << "0 and 0 are unordered"; } Output: 0 and 0 are equal NotesThreeway comparison can be automatically generated for class types, see default comparisons. If both of the operands are arrays, threeway comparison is illformed. unsigned int i = 1; auto r = 1 < i; // existing pitfall: returns ‘false’ auto r2 = 1 <=> i; // Error: narrowing conversion required
 (since C++20) 
Comparison operators are overloaded for many classes in the standard library.
(removed in C++20)  checks whether the objects refer to the same type (public member function of std::type_info ) 
(removed in C++20)(removed in C++20)(C++20)  compares two error_code s (function) 
(removed in C++20)(removed in C++20)(C++20)  compares error_condition s and error_code s (function) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares the values in the pair (function template) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares the values in the tuple (function template) 
(removed in C++20)  compares the contents (public member function of std::bitset<N> ) 
(removed in C++20)  compares two allocator instances (public member function of std::allocator<T> ) 
(removed in C++20)(C++20)  compares to another unique_ptr or with nullptr (function template) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  compares with another shared_ptr or with nullptr (function template) 
(removed in C++20)  compares a std::function with nullptr (function template) 
(C++11)(C++11)(removed in C++20)(C++11)(C++11)(C++11)(C++11)(C++20)  compares two durations (function template) 
(C++11)(C++11)(removed in C++20)(C++11)(C++11)(C++11)(C++11)(C++20)  compares two time points (function template) 
(removed in C++20)  compares two scoped_allocator_adaptor instances (function template) 
(removed in C++20)(C++20)  compares the underlying std::type_info objects (public member function of std::type_index ) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares two strings (function template) 
(removed in C++20)  equality comparison between locale objects (public member function of std::locale ) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares the values in the array (function template) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares the values in the deque (function template) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares the values in the forward_list (function template) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares the values in the list (function template) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares the values in the vector (function template) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares the values in the map (function template) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares the values in the multimap (function template) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares the values in the set (function template) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  lexicographically compares the values in the multiset (function template) 
(removed in C++20)  compares the values in the unordered_map (function template) 
(removed in C++20)  compares the values in the unordered_multimap (function template) 
(removed in C++20)  compares the values in the unordered_set (function template) 
(removed in C++20)  compares the values in the unordered_multiset (function template) 
(C++20)  lexicographically compares the values in the queue (function template) 
(C++20)  lexicographically compares the values in the stack (function template) 
(C++20)  compares the underlying iterators (function template) 
(C++11)(C++11)(removed in C++20)(C++11)(C++11)(C++11)(C++11)(C++20)  compares the underlying iterators (function template) 
(removed in C++20)  compares two istream_iterator s (function template) 
(removed in C++20)  compares two istreambuf_iterator s (function template) 
(removed in C++20)  compares two complex numbers or a complex and a scalar (function template) 
compares two valarrays or a valarray with a value (function template) 

(C++11)(C++11)(removed in C++20)  compares the internal states of two pseudorandom number engines (function) 
(C++11)(C++11)(removed in C++20)  compares two distribution objects (function) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  compares a sub_match with another sub_match , a string, or a character (function template) 
(removed in C++20)  lexicographically compares the values in the two match result (function template) 
(removed in C++20)  compares two regex_iterator s (public member function of std::regex_iterator<BidirIt,CharT,Traits> ) 
(removed in C++20)  compares two regex_token_iterator s (public member function of std::regex_token_iterator<BidirIt,CharT,Traits> ) 
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)  compares two thread::id objects (function) 
The namespace std::rel_ops
provides generic operators !=
, >
, <=
, and >=
:
Defined in header <utility> 


Defined in namespace std::rel_ops 

(deprecated in C++20)  automatically generates comparison operators based on userdefined operator== and operator< (function template) 
The following behaviorchanging defect reports were applied retroactively to previously published C++ standards.
DR  Applied to  Behavior as published  Correct behavior 

CWG 583  C++98  all six comparison operators could be used to compare a pointer with a null pointer constant  only equality operators allowed 
CWG 661  C++98  the actual semantics of arithmetic comparisons (e.g. whether 1 < 2 yields true or false ) were unspecified  specification added 
CWG 879  C++98  pointers to function types and pointers to void did not have builtin comparisons  added comparison specification for these pointers 
CWG 1512  C++98  the rule of composite pointer type was incomplete, and thus did not allow comparison between int** and const int**  made complete 
CWG 1596  C++98  nonarray objects were considered to belong to arrays with one element only for the purpose of pointer arithmetic  the rule is also applied to comparison 
CWG 1598  C++98  two pointers to members of classes that are different and neither is the base class of the other did not compare equal even if the offsets of the pointed members can be the same  the result is unspecified in this case 
CWG 1858  C++98  it was not clear whether two pointers to members that refer to different members of the same union compare equal as if they refer to the same member  they compare equal in this case 
CWG 2419  C++98  a pointer to nonarray object was only treated as a pointer to the first element of an array with size 1 in pointer comparison if the pointer is obtained by &  applies to all pointers to nonarray objects 
Common operators  

assignment  increment decrement  arithmetic  logical  comparison  member access  other 







Special operators  

C documentation for Comparison operators 
© cppreference.com
Licensed under the Creative Commons AttributionShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/operator_comparison