[comparisons]

# 22 General utilities library [[utilities]](./#utilities)

## 22.10 Function objects [[function.objects]](function.objects#comparisons)

### 22.10.8 Comparisons [comparisons]

#### [22.10.8.1](#general) General [[comparisons.general]](comparisons.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12260)

The library provides basic function object classes for all of the comparison
operators in the language ([[expr.rel]](expr.rel "7.6.9 Relational operators"), [[expr.eq]](expr.eq "7.6.10 Equality operators"))[.](#general-1.sentence-1)

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12264)

For templates less, greater, less_equal, andgreater_equal, the specializations for any pointer type
yield a result consistent with the
implementation-defined strict total order over pointers ([[defns.order.ptr]](defns.order.ptr "3.28 implementation-defined strict total order over pointers"))[.](#general-2.sentence-1)

[*Note [1](#general-note-1)*:

If a < b is well-defined
for pointers a and b of type P,
then (a < b) == less<P>()(a, b),(a > b) == greater<P>()(a, b), and so forth[.](#general-2.sentence-2)

â *end note*]

For template specializations less<void>, greater<void>,less_equal<void>, and greater_equal<void>,
if the call operator calls a built-in operator comparing pointers,
the call operator yields a result consistent
with the implementation-defined strict total order over pointers[.](#general-2.sentence-3)

#### [22.10.8.2](#equal.to) Class template equal_to [[comparisons.equal.to]](comparisons.equal.to)

[ð](#lib:equal_to)

`template<class T = void> struct equal_to {
  constexpr bool operator()(const T& x, const T& y) const;
};
`

[ð](#lib:operator(),equal_to)

`constexpr bool operator()(const T& x, const T& y) const;
`

[1](#equal.to-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12296)

*Returns*: x == y[.](#equal.to-1.sentence-1)

[ð](#lib:equal_to%3c%3e)

`template<> struct equal_to<void> {
  template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) == std::forward<U>(u));

  using is_transparent = unspecified;
};
`

[ð](#lib:operator(),equal_to%3c%3e)

`template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) == std::forward<U>(u));
`

[2](#equal.to-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12318)

*Returns*: std​::​forward<T>(t) == std​::​forward<U>(u)[.](#equal.to-2.sentence-1)

#### [22.10.8.3](#not.equal.to) Class template not_equal_to [[comparisons.not.equal.to]](comparisons.not.equal.to)

[ð](#lib:not_equal_to)

`template<class T = void> struct not_equal_to {
  constexpr bool operator()(const T& x, const T& y) const;
};
`

[ð](#lib:operator(),not_equal_to)

`constexpr bool operator()(const T& x, const T& y) const;
`

[1](#not.equal.to-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12338)

*Returns*: x != y[.](#not.equal.to-1.sentence-1)

[ð](#lib:not_equal_to%3c%3e)

`template<> struct not_equal_to<void> {
  template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) != std::forward<U>(u));

  using is_transparent = unspecified;
};
`

[ð](#lib:operator(),not_equal_to%3c%3e)

`template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) != std::forward<U>(u));
`

[2](#not.equal.to-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12360)

*Returns*: std​::​forward<T>(t) != std​::​forward<U>(u)[.](#not.equal.to-2.sentence-1)

#### [22.10.8.4](#greater) Class template greater [[comparisons.greater]](comparisons.greater)

[ð](#lib:greater)

`template<class T = void> struct greater {
  constexpr bool operator()(const T& x, const T& y) const;
};
`

[ð](#lib:operator(),greater)

`constexpr bool operator()(const T& x, const T& y) const;
`

[1](#greater-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12380)

*Returns*: x > y[.](#greater-1.sentence-1)

[ð](#lib:greater%3c%3e)

`template<> struct greater<void> {
  template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) > std::forward<U>(u));

  using is_transparent = unspecified;
};
`

[ð](#lib:operator(),greater%3c%3e)

`template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) > std::forward<U>(u));
`

[2](#greater-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12402)

*Returns*: std​::​forward<T>(t) > std​::​forward<U>(u)[.](#greater-2.sentence-1)

#### [22.10.8.5](#less) Class template less [[comparisons.less]](comparisons.less)

[ð](#lib:less)

`template<class T = void> struct less {
  constexpr bool operator()(const T& x, const T& y) const;
};
`

[ð](#lib:operator(),less)

`constexpr bool operator()(const T& x, const T& y) const;
`

[1](#less-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12422)

*Returns*: x < y[.](#less-1.sentence-1)

[ð](#lib:less%3c%3e)

`template<> struct less<void> {
  template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) < std::forward<U>(u));

  using is_transparent = unspecified;
};
`

[ð](#lib:operator(),less%3c%3e)

`template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) < std::forward<U>(u));
`

[2](#less-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12444)

*Returns*: std​::​forward<T>(t) < std​::​forward<U>(u)[.](#less-2.sentence-1)

#### [22.10.8.6](#greater.equal) Class template greater_equal [[comparisons.greater.equal]](comparisons.greater.equal)

[ð](#lib:greater_equal)

`template<class T = void> struct greater_equal {
  constexpr bool operator()(const T& x, const T& y) const;
};
`

[ð](#lib:operator(),greater_equal)

`constexpr bool operator()(const T& x, const T& y) const;
`

[1](#greater.equal-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12464)

*Returns*: x >= y[.](#greater.equal-1.sentence-1)

[ð](#lib:greater_equal%3c%3e)

`template<> struct greater_equal<void> {
  template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) >= std::forward<U>(u));

  using is_transparent = unspecified;
};
`

[ð](#lib:operator(),greater_equal%3c%3e)

`template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) >= std::forward<U>(u));
`

[2](#greater.equal-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12486)

*Returns*: std​::​forward<T>(t) >= std​::​forward<U>(u)[.](#greater.equal-2.sentence-1)

#### [22.10.8.7](#less.equal) Class template less_equal [[comparisons.less.equal]](comparisons.less.equal)

[ð](#lib:less_equal)

`template<class T = void> struct less_equal {
  constexpr bool operator()(const T& x, const T& y) const;
};
`

[ð](#lib:operator(),less_equal)

`constexpr bool operator()(const T& x, const T& y) const;
`

[1](#less.equal-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12506)

*Returns*: x <= y[.](#less.equal-1.sentence-1)

[ð](#lib:less_equal%3c%3e)

`template<> struct less_equal<void> {
  template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) <= std::forward<U>(u));

  using is_transparent = unspecified;
};
`

[ð](#lib:operator(),less_equal%3c%3e)

`template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) <= std::forward<U>(u));
`

[2](#less.equal-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12528)

*Returns*: std​::​forward<T>(t) <= std​::​forward<U>(u)[.](#less.equal-2.sentence-1)

#### [22.10.8.8](#three.way) Class compare_three_way [[comparisons.three.way]](comparisons.three.way)

[ð](#lib:compare_three_way)

namespace std {struct compare_three_way {template<class T, class U>constexpr auto operator()(T&& t, U&& u) const; using is_transparent = *unspecified*; };}

[ð](#three.way-itemdecl:1)

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

[1](#three.way-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12553)

*Constraints*: T and U satisfy [three_way_comparable_with](cmp.concept#concept:three_way_comparable_with "17.12.4 Concept three_­way_­comparable [cmp.concept]")[.](#three.way-1.sentence-1)

[2](#three.way-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12557)

*Preconditions*: If the expression std​::​forward<T>(t) <=> std​::​forward<U>(u) results in
a call to a built-in operator <=> comparing pointers of type P,
the conversion sequences from both T and U to P are equality-preserving ([[concepts.equality]](concepts.equality "18.2 Equality preservation"));
otherwise, T and U model [three_way_comparable_with](cmp.concept#concept:three_way_comparable_with "17.12.4 Concept three_­way_­comparable [cmp.concept]")[.](#three.way-2.sentence-1)

[3](#three.way-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L12565)

*Effects*: 

- [(3.1)](#three.way-3.1)

If the expression std​::​forward<T>(t) <=> std​::​forward<U>(u) results in
 a call to a built-in operator <=> comparing pointers of type P,
 returns strong_ordering​::​less if (the converted value of) t precedes u in the implementation-defined strict total order
 over pointers ([[defns.order.ptr]](defns.order.ptr "3.28 implementation-defined strict total order over pointers")), strong_ordering​::​greater if u precedes t, and
 otherwise strong_ordering​::​equal.

- [(3.2)](#three.way-3.2)

Otherwise, equivalent to: return std​::​forward<T>(t) <=> std​::​forward<U>(u);
