**Section:** 22.3.3 [pairs.spec] **Status:** WP
**Submitter:** Barry Revzin **Opened:** 2023-01-28 **Last modified:** 2023-02-13 11:31:17 UTC

**Priority: **2

**View all other** issues in [pairs.spec].

**View all issues with** WP status.

**Discussion:**

Consider this example:

#include <algorithm> #include <ranges> int main() { int a[3] = {1, 2, -1}; int b[3] = {1, 4, 1}; std::ranges::sort(std::views::zip(a, b)); }

This is currently valid C++23 code, but wasn't before P2165 (Compatibility between `tuple`, `pair`
and *tuple-like* objects). Before P2165, `zip(a, b)` returned a range whose reference was
`std::pair<int&, int&>` and whose `value_type` was `std::pair<int, int>` and
`std::pair`, unlike `std::tuple`, does not have any heterogeneous comparisons — which is required to
satisfy the `sortable` concept.

While the zip family of range adapters no longer has this problem, nothing prevents users from themselves creating a range
whose reference type is `pair<T&, U&>` and whose `value_type` is `pair<T, U>`
(which is now a valid range after the zip paper) and then discovering that this range isn't sortable, even though the
equivalent using `tuple` is.

Suggested resolution:

Change `pair`'s comparison operators from comparing two arguments of type `const pair<T1, T2>&`
to instead comparing arguments of types `const pair<T1, T2>&` and `const pair<U1, U2>&`.

*[2023-02-05; Barry provides wording]*

*[2023-02-06; Reflector poll]*

Set priority to 2 after reflector poll.

*[Issaquah 2023-02-07; LWG]*

Move to Immediate for C++23

*[2023-02-13 Status changed: Immediate → WP.]*

**Proposed resolution:**

This wording is relative to N4928.

Modify 22.2.1 [utility.syn], header

`<utility>`synopsis, as indicated:[…] //

*22.3.3 [pairs.spec], pair specialized algorithms*template<class T1, class T2, class U1, class U2> constexpr bool operator==(const pair<T1, T2>&, const pair<~~T~~U1,~~T~~U2>&); template<class T1, class T2, class U1, class U2> constexpr common_comparison_category_t<*synth-three-way-result*<T1, U1>,*synth-three-way-result*<T2, U2>> operator<=>(const pair<T1, T2>&, const pair<~~T~~U1,~~T~~U2>&); […]Modify 22.3.3 [pairs.spec] as indicated:

template<class T1, class T2, class U1, class U2> constexpr bool operator==(const pair<T1, T2>& x, const pair<

~~T~~U1,~~T~~U2>& y);-1- […]

-2- […]

template<class T1, class T2, class U1, class U2> constexpr common_comparison_category_t<

*synth-three-way-result*<T1, U1>,*synth-three-way-result*<T2, U2>> operator<=>(const pair<T1, T2>& x, const pair<~~T~~U1,~~T~~U2>& y);-3- […]