Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/utility/compare/compare three way"

From cppreference.com
< cpp‎ | utility
(P1614R2)
 
(Wording update. All usages of {{cpp/utility/functional/pointer order}} are eliminated.)
 
(16 intermediate revisions by 6 users not shown)
Line 1: Line 1:
 
{{cpp/title|compare_three_way}}
 
{{cpp/title|compare_three_way}}
{{cpp/utility/navbar}}
+
{{cpp/utility/functional/navbar}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | compare }}
+
{{dcl header|compare}}
{{dcl | since=c++20 |
+
{{dcl header|functional}}
 +
{{dcl|since=c++20|
 
struct compare_three_way;
 
struct compare_three_way;
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
Function object for performing comparisons. Deduces the parameter types of the function call operator from the arguments (but not the return type).
+
Function object for performing comparisons. Deduces the parameter types and the return type of the function call operator.
  
=== Member types ===
+
===Nested types===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc hitem|Member type | Definition}}
+
{{dsc hitem|Nested type|Definition}}
{{dsc | {{tt|is_transparent}} | /* unspecified */}}
+
{{dsc|{{tt|is_transparent}}|[[cpp/utility/functional#Transparent function objects|unspecified]]}}
 
{{dsc end}}
 
{{dsc end}}
  
 
===Member functions===
 
===Member functions===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc mem fun | operator() | nolink=true | obtains the result of three-way comparison on both arguments}}
+
{{dsc mem fun|operator()|nolink=true|obtains the result of three-way comparison on both arguments}}
 
{{dsc end}}
 
{{dsc end}}
  
 
{{member|1={{small|std::compare_three_way::}}operator()|2=
 
{{member|1={{small|std::compare_three_way::}}operator()|2=
{{dcl begin}}
+
{{ddcl|
{{dcl|1=
+
template< class T, class U >
template<class T, class U>
+
constexpr auto operator()( T&& t, U&& u ) const;
    requires three_way_comparable_with<T, U> {{!!}}
+
            /* std::declval<T>() <=> std::declval<U>() resolves to
+
                a built-in operator comparing pointers */
+
constexpr auto operator()(T&& t, U&& u) const;
+
 
}}
 
}}
{{dcl end}}
 
 
Compares {{tt|t}} and {{tt|u}}, equivalent to {{c|1=return std::forward<T>(t) <=> std::forward<U>(u);}}, except when that expression resolves to a call to a builtin {{c|1=operator<=>}} comparing pointers.
 
 
When a call would invoke a built-in operator comparing pointers of type {{tt|P}}, the result is instead determined as follows:
 
* Returns {{c|std::strong_ordering::less}} if the (possibly converted) value of the first argument precedes the (possibly converted) value of the second argument in the implementation-defined strict total ordering over all pointer values of type {{tt|P}}. This strict total ordering is consistent with the partial order imposed by the builtin operators {{tt|<}}, {{tt|>}}, {{tt|<{{=}}}}, and {{tt|>{{=}}}}.
 
* Otherwise, returns {{c|std::strong_ordering::greater}} if (possibly converted) value of the second argument precedes the (possibly converted) value of the first argument in the same strict total ordering.
 
* Otherwise, returns {{c|std::strong_ordering::equal}}.
 
  
The behavior is undefined unless the the conversion sequences from both {{tt|T}} and {{tt|U}} to {{tt|P}} are equality-preserving (see below).
+
Given the expression {{c|1=std::forward<T>(t) <=> std::forward<U>(u)}} as {{c|expr}}:
 +
* If {{c|expr}} results in a call to [[cpp/language/operator comparison#Built-in pointer equality comparison|built-in]] {{c/core|1=operator<=>}} comparing pointers, given the {{lsd|cpp/language/pointer#Composite pointer type}} of {{c|t}} and {{c|u}} as {{tt|P}}:
 +
:* Compares the two converted pointers (of type {{tt|P}}) in the [[cpp/language/operator comparison#Pointer total order|implementation-defined strict total order over pointers]]:
 +
::* If {{c|t}} precedes {{c|u}}, returns {{ltt|cpp/utility/compare/strong_ordering|std::strong_ordering::less}}.
 +
::* If {{c|u}} precedes {{c|t}}, returns {{ltt|cpp/utility/compare/strong_ordering|std::strong_ordering::greater}}.
 +
::* Otherwise, returns {{ltt|cpp/utility/compare/strong_ordering|std::strong_ordering::equal}}.
 +
:* If the conversion sequence from {{tt|T}} to {{tt|P}} or the conversion sequence from {{tt|U}} to {{tt|P}} is not [[cpp/concepts#Equality preservation|equality-preserving]], the behavior is undefined.
 +
* Otherwise:
 +
:* Returns the result of {{c|expr}}.
 +
:* If {{c|std::three_way_comparable_with<T, U>}} is not modeled, the behavior is undefined.
  
{{cpp/concepts/equality preservation|skip-requires=yes}}
+
{{cpp/enable if|{{c|std::three_way_comparable_with<T, U>}} is satisfied}}.
 
}}
 
}}
  
 
===Example===
 
===Example===
 
{{example|code=
 
{{example|code=
 +
#include <compare>
 
#include <iostream>
 
#include <iostream>
#include <compare>
+
 
<!--
+
struct Rational
//does not support <=>
+
{
struct Rational_1 {
+
 
     int num;
 
     int num;
 
     int den; // > 0
 
     int den; // > 0
 +
   
 +
    // Although the comparison X <=> Y will work, a direct call
 +
    // to std::compare_three_way{}(X, Y) requires the operator==
 +
    // be defined, to satisfy the std::three_way_comparable_with.
 +
    constexpr bool operator==(Rational const&) const = default;
 
};
 
};
 
inline constexpr bool operator<(Rational_1 lhs, Rational_1 rhs)
 
{
 
    return lhs.num * rhs.den < rhs.num * lhs.den;
 
}
 
 
inline constexpr bool operator==(Rational_1 lhs, Rational_1 rhs)
 
{
 
    return lhs.num * rhs.den == rhs.num * lhs.den;
 
}
 
-->
 
  
struct Rational_2 {
+
constexpr std::weak_ordering operator<=>(Rational lhs, Rational rhs)
    int num;
+
    int den; // > 0
+
};
+
+
inline constexpr std::weak_ordering operator<=>(Rational_2 lhs, Rational_2 rhs)
+
 
{
 
{
 
     return lhs.num * rhs.den <=> rhs.num * lhs.den;
 
     return lhs.num * rhs.den <=> rhs.num * lhs.den;
 
}
 
}
+
 
 
void print(std::weak_ordering value)
 
void print(std::weak_ordering value)
 
{
 
{
     if (value == 0)
+
     value < 0 ? std::cout << "less\n" :
        std::cout << "equal\n";
+
     value > 0 ? std::cout << "greater\n" :
     else if (value < 0)
+
                std::cout << "equal\n";
        std::cout << "less\n";
+
    else
+
        std::cout << "greater\n";
+
 
}
 
}
+
 
 
int main()
 
int main()
 
{
 
{
<!--
+
     Rational a{6, 5};
     Rational_1 a{1,2};
+
     Rational b{8, 7};
    Rational_1 b{3,4};
+
     print(a <=> b);
//  print(a <=> b);                //doesn't work
+
     print(std::compare_three_way{}(a, b));
    print(std::compare_3way(a,b)); //works, defaults to < and ==
+
-->
+
    Rational_2 c{6,5};
+
     Rational_2 d{8,7};
+
     print(c <=> d);
+
     print(std::compare_three_way{}(c,d));
+
 
}
 
}
| output=
+
|output=
less
+
 
greater
 
greater
 
greater
 
greater
 
}}
 
}}
 +
 +
===Defect reports===
 +
{{dr list begin}}
 +
{{dr list item|wg=lwg|dr=3530|std=C++20|before=syntactic checks were relaxed while comparing pointers|after=only semantic requirements are relaxed}}
 +
{{dr list end}}
  
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
 +
{{dsc inc|cpp/utility/functional/ranges/dsc equal_to}}
 +
{{dsc inc|cpp/utility/functional/ranges/dsc not_equal_to}}
 +
{{dsc inc|cpp/utility/functional/ranges/dsc less}}
 +
{{dsc inc|cpp/utility/functional/ranges/dsc greater}}
 +
{{dsc inc|cpp/utility/functional/ranges/dsc less_equal}}
 +
{{dsc inc|cpp/utility/functional/ranges/dsc greater_equal}}
 
{{dsc end}}
 
{{dsc end}}
  
{{langlinks|ja|zh}}
+
{{langlinks|de|es|ja|ru|zh}}

Latest revision as of 19:58, 2 January 2024

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
Function objects
Function invocation
(C++17)(C++23)
Identity function object
(C++20)
Transparent operator wrappers
(C++14)
(C++14)
(C++14)
(C++14)  
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)

Old binders and adaptors
(until C++17*)
(until C++17*)
(until C++17*)
(until C++17*)  
(until C++17*)
(until C++17*)(until C++17*)(until C++17*)(until C++17*)
(until C++20*)
(until C++20*)
(until C++17*)(until C++17*)
(until C++17*)(until C++17*)

(until C++17*)
(until C++17*)(until C++17*)(until C++17*)(until C++17*)
(until C++20*)
(until C++20*)
 
Defined in header <compare>
Defined in header <functional>
struct compare_three_way;
(since C++20)

Function object for performing comparisons. Deduces the parameter types and the return type of the function call operator.

Contents

[edit] Nested types

Nested type Definition
is_transparent unspecified

[edit] Member functions

operator()
obtains the result of three-way comparison on both arguments
(public member function)

std::compare_three_way::operator()

template< class T, class U >
constexpr auto operator()( T&& t, U&& u ) const;

Given the expression std::forward<T>(t) <=> std::forward<U>(u) as expr:

  • If the conversion sequence from T to P or the conversion sequence from U to P is not equality-preserving, the behavior is undefined.
  • Otherwise:

This overload participates in overload resolution only if std::three_way_comparable_with<T, U> is satisfied.

[edit] Example

#include <compare>
#include <iostream>
 
struct Rational
{
    int num;
    int den; // > 0
 
    // Although the comparison X <=> Y will work, a direct call
    // to std::compare_three_way{}(X, Y) requires the operator==
    // be defined, to satisfy the std::three_way_comparable_with.
    constexpr bool operator==(Rational const&) const = default;
};
 
constexpr std::weak_ordering operator<=>(Rational lhs, Rational rhs)
{
    return lhs.num * rhs.den <=> rhs.num * lhs.den;
}
 
void print(std::weak_ordering value)
{
    value < 0 ? std::cout << "less\n" :
    value > 0 ? std::cout << "greater\n" :
                std::cout << "equal\n";
}
 
int main()
{
    Rational a{6, 5};
    Rational b{8, 7};
    print(a <=> b);
    print(std::compare_three_way{}(a, b));
}

Output:

greater
greater

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 3530 C++20 syntactic checks were relaxed while comparing pointers only semantic requirements are relaxed

[edit] See also

constrained function object implementing x == y
(class) [edit]
constrained function object implementing x != y
(class) [edit]
constrained function object implementing x < y
(class) [edit]
constrained function object implementing x > y
(class) [edit]
constrained function object implementing x <= y
(class) [edit]
constrained function object implementing x >= y
(class) [edit]