Files
2025-10-25 03:02:53 +03:00

840 lines
28 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[pairs]
# 22 General utilities library [[utilities]](./#utilities)
## 22.3 Pairs [pairs]
### [22.3.1](#general) General [[pairs.general]](pairs.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L737)
The library provides a template for heterogeneous pairs of values[.](#general-1.sentence-1)
The library also provides a matching function template to simplify
their construction and several templates that provide access to pair objects as if they were tuple objects (see [[tuple.helper]](tuple.helper "22.4.7Tuple helper classes") and [[tuple.elem]](tuple.elem "22.4.8Element access"))[.](#general-1.sentence-2)
### [22.3.2](#pair) Class template pair [[pairs.pair]](pairs.pair)
[🔗](#lib:pair_)
namespace std {template<class T1, class T2>struct pair {using first_type = T1; using second_type = T2;
T1 first;
T2 second;
pair(const pair&) = default;
pair(pair&&) = default; constexpr explicit(*see below*) pair(); constexpr explicit(*see below*) pair(const T1& x, const T2& y); template<class U1 = T1, class U2 = T2>constexpr explicit(*see below*) pair(U1&& x, U2&& y); template<class U1, class U2>constexpr explicit(*see below*) pair(pair<U1, U2>& p); template<class U1, class U2>constexpr explicit(*see below*) pair(const pair<U1, U2>& p); template<class U1, class U2>constexpr explicit(*see below*) pair(pair<U1, U2>&& p); template<class U1, class U2>constexpr explicit(*see below*) pair(const pair<U1, U2>&& p); template<[*pair-like*](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]") P>constexpr explicit(*see below*) pair(P&& p); template<class... Args1, class... Args2>constexpr pair(piecewise_construct_t,
tuple<Args1...> first_args, tuple<Args2...> second_args); constexpr pair& operator=(const pair& p); constexpr const pair& operator=(const pair& p) const; template<class U1, class U2>constexpr pair& operator=(const pair<U1, U2>& p); template<class U1, class U2>constexpr const pair& operator=(const pair<U1, U2>& p) const; constexpr pair& operator=(pair&& p) noexcept(*see below*); constexpr const pair& operator=(pair&& p) const; template<class U1, class U2>constexpr pair& operator=(pair<U1, U2>&& p); template<class U1, class U2>constexpr const pair& operator=(pair<U1, U2>&& p) const; template<[*pair-like*](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]") P>constexpr pair& operator=(P&& p); template<[*pair-like*](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]") P>constexpr const pair& operator=(P&& p) const; constexpr void swap(pair& p) noexcept(*see below*); constexpr void swap(const pair& p) const noexcept(*see below*); }; template<class T1, class T2> pair(T1, T2) -> pair<T1, T2>;}
[1](#pair-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L806)
Constructors and member functions of pair do not throw exceptions unless one of
the element-wise operations specified to be called for that operation
throws an exception[.](#pair-1.sentence-1)
[2](#pair-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L811)
The defaulted move and copy constructor, respectively, of pair is a constexpr function if and only if all required element-wise
initializations for move and copy, respectively,
would be constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers"))[.](#pair-2.sentence-1)
[3](#pair-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L817)
If (is_trivially_destructible_v<T1> && is_trivially_destructible_v<T2>) is true, then the destructor of pair is trivial[.](#pair-3.sentence-1)
[4](#pair-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L821)
pair<T, U> is a structural type ([[temp.param]](temp.param#term.structural.type "13.2Template parameters"))
if T and U are both structural types[.](#pair-4.sentence-1)
Two values p1 and p2 of type pair<T, U> are template-argument-equivalent ([[temp.type]](temp.type "13.6Type equivalence")) if and only ifp1.first and p2.first are template-argument-equivalent andp1.second and p2.second are template-argument-equivalent[.](#pair-4.sentence-2)
[🔗](#lib:pair,constructor)
`constexpr explicit(see below) pair();
`
[5](#pair-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L835)
*Constraints*:
- [(5.1)](#pair-5.1)
is_default_constructible_v<T1> is true and
- [(5.2)](#pair-5.2)
is_default_constructible_v<T2> is true[.](#pair-5.sentence-1)
[6](#pair-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L842)
*Effects*: Value-initializes first and second[.](#pair-6.sentence-1)
[7](#pair-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L846)
*Remarks*: The expression inside explicit evaluates to true if and only if either T1 orT2 is not implicitly default-constructible[.](#pair-7.sentence-1)
[*Note [1](#pair-note-1)*:
This behavior can be implemented with a trait that checks
whether a const T1& or a const T2& can be initialized with {}[.](#pair-7.sentence-2)
— *end note*]
[🔗](#lib:pair,constructor_)
`constexpr explicit(see below) pair(const T1& x, const T2& y);
`
[8](#pair-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L864)
*Constraints*:
- [(8.1)](#pair-8.1)
is_copy_constructible_v<T1> is true and
- [(8.2)](#pair-8.2)
is_copy_constructible_v<T2> is true[.](#pair-8.sentence-1)
[9](#pair-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L871)
*Effects*: Initializes first with x and second with y[.](#pair-9.sentence-1)
[10](#pair-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L875)
*Remarks*: The expression inside explicit is equivalent to:!is_convertible_v<const T1&, T1> || !is_convertible_v<const T2&, T2>
[🔗](#lib:pair,constructor__)
`template<class U1 = T1, class U2 = T2> constexpr explicit(see below) pair(U1&& x, U2&& y);
`
[11](#pair-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L889)
*Constraints*:
- [(11.1)](#pair-11.1)
is_constructible_v<T1, U1> is true and
- [(11.2)](#pair-11.2)
is_constructible_v<T2, U2> is true[.](#pair-11.sentence-1)
[12](#pair-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L896)
*Effects*: Initializes first withstd::forward<U1>(x) and second with std::forward<U2>(y)[.](#pair-12.sentence-1)
[13](#pair-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L902)
*Remarks*: The expression inside explicit is equivalent to:!is_convertible_v<U1, T1> || !is_convertible_v<U2, T2>
This constructor is defined as deleted ifreference_constructs_from_temporary_v<first_type, U1&&> is true orreference_constructs_from_temporary_v<second_type, U2&&> is true[.](#pair-13.sentence-2)
[🔗](#lib:pair,constructor___)
`template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>& p);
template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>& p);
template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>&& p);
template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>&& p);
template<[pair-like](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]") P> constexpr explicit(see below) pair(P&& p);
`
[14](#pair-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L925)
Let *FWD*(u) be static_cast<decltype(u)>(u)[.](#pair-14.sentence-1)
[15](#pair-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L928)
*Constraints*:
- [(15.1)](#pair-15.1)
For the last overload,remove_cvref_t<P> is not a specialization of ranges::subrange,
- [(15.2)](#pair-15.2)
is_constructible_v<T1, decltype(get<0>(*FWD*(p)))> is true, and
- [(15.3)](#pair-15.3)
is_constructible_v<T2, decltype(get<1>(*FWD*(p)))> is true[.](#pair-15.sentence-1)
[16](#pair-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L942)
*Effects*: Initializes first with get<0>(*FWD*(p)) andsecond with get<1>(*FWD*(p))[.](#pair-16.sentence-1)
[17](#pair-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L947)
*Remarks*: The expression inside explicit is equivalent to:!is_convertible_v<decltype(get<0>(*FWD*(p))), T1> ||!is_convertible_v<decltype(get<1>(*FWD*(p))), T2>
The constructor is defined as deleted ifreference_constructs_from_temporary_v<first_type, decltype(get<0>(*FWD*(p)))> || reference_constructs_from_temporary_v<second_type, decltype(get<1>(*FWD*(p)))> is true[.](#pair-17.sentence-2)
[🔗](#lib:pair,constructor____)
`template<class... Args1, class... Args2>
constexpr pair(piecewise_construct_t,
tuple<Args1...> first_args, tuple<Args2...> second_args);
`
[18](#pair-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L970)
*Mandates*:
- [(18.1)](#pair-18.1)
is_constructible_v<T1, Args1...> is true and
- [(18.2)](#pair-18.2)
is_constructible_v<T2, Args2...> is true[.](#pair-18.sentence-1)
[19](#pair-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L977)
*Effects*: Initializes first with arguments of typesArgs1... obtained by forwarding the elements of first_args and initializes second with arguments of types Args2... obtained by forwarding the elements of second_args[.](#pair-19.sentence-1)
(Here, forwarding
an element x of type U within a tuple object means callingstd::forward<U>(x)[.](#pair-19.sentence-2))
This form of construction, whereby constructor
arguments for first and second are each provided in a separatetuple object, is called [*piecewise construction*](#def:piecewise_construction "22.3.2Class template pair[pairs.pair]")[.](#pair-19.sentence-3)
[*Note [2](#pair-note-2)*:
If a data member of pair is of reference type and
its initialization binds it to a temporary object,
the program is ill-formed ([[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#pair-19.sentence-4)
— *end note*]
[🔗](#lib:operator=,pair)
`constexpr pair& operator=(const pair& p);
`
[20](#pair-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1000)
*Effects*: Assigns p.first to first and p.second to second[.](#pair-20.sentence-1)
[21](#pair-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1004)
*Returns*: *this[.](#pair-21.sentence-1)
[22](#pair-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1008)
*Remarks*: This operator is defined as deleted unlessis_copy_assignable_v<T1> is true andis_copy_assignable_v<T2> is true[.](#pair-22.sentence-1)
[🔗](#lib:operator=,pair_)
`constexpr const pair& operator=(const pair& p) const;
`
[23](#pair-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1021)
*Constraints*:
- [(23.1)](#pair-23.1)
is_copy_assignable_v<const T1> is true and
- [(23.2)](#pair-23.2)
is_copy_assignable_v<const T2> is true[.](#pair-23.sentence-1)
[24](#pair-24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1030)
*Effects*: Assigns p.first to first and p.second to second[.](#pair-24.sentence-1)
[25](#pair-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1034)
*Returns*: *this[.](#pair-25.sentence-1)
[🔗](#lib:operator=,pair__)
`template<class U1, class U2> constexpr pair& operator=(const pair<U1, U2>& p);
`
[26](#pair-26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1045)
*Constraints*:
- [(26.1)](#pair-26.1)
is_assignable_v<T1&, const U1&> is true and
- [(26.2)](#pair-26.2)
is_assignable_v<T2&, const U2&> is true[.](#pair-26.sentence-1)
[27](#pair-27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1052)
*Effects*: Assigns p.first to first and p.second to second[.](#pair-27.sentence-1)
[28](#pair-28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1056)
*Returns*: *this[.](#pair-28.sentence-1)
[🔗](#lib:operator=,pair___)
`template<class U1, class U2> constexpr const pair& operator=(const pair<U1, U2>& p) const;
`
[29](#pair-29)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1067)
*Constraints*:
- [(29.1)](#pair-29.1)
is_assignable_v<const T1&, const U1&> is true, and
- [(29.2)](#pair-29.2)
is_assignable_v<const T2&, const U2&> is true[.](#pair-29.sentence-1)
[30](#pair-30)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1076)
*Effects*: Assigns p.first to first and p.second to second[.](#pair-30.sentence-1)
[31](#pair-31)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1080)
*Returns*: *this[.](#pair-31.sentence-1)
[🔗](#lib:operator=,pair____)
`constexpr pair& operator=(pair&& p) noexcept(see below);
`
[32](#pair-32)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1091)
*Constraints*:
- [(32.1)](#pair-32.1)
is_move_assignable_v<T1> is true and
- [(32.2)](#pair-32.2)
is_move_assignable_v<T2> is true[.](#pair-32.sentence-1)
[33](#pair-33)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1098)
*Effects*: Assigns std::forward<T1>(p.first) to first andstd::forward<T2>(p.second) to second[.](#pair-33.sentence-1)
[34](#pair-34)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1103)
*Returns*: *this[.](#pair-34.sentence-1)
[35](#pair-35)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1107)
*Remarks*: The exception specification is equivalent to:is_nothrow_move_assignable_v<T1> && is_nothrow_move_assignable_v<T2>
[🔗](#lib:operator=,pair_____)
`constexpr const pair& operator=(pair&& p) const;
`
[36](#pair-36)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1121)
*Constraints*:
- [(36.1)](#pair-36.1)
is_assignable_v<const T1&, T1> is true and
- [(36.2)](#pair-36.2)
is_assignable_v<const T2&, T2> is true[.](#pair-36.sentence-1)
[37](#pair-37)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1130)
*Effects*: Assigns std::forward<T1>(p.first) to first andstd::forward<T2>(p.second) to second[.](#pair-37.sentence-1)
[38](#pair-38)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1135)
*Returns*: *this[.](#pair-38.sentence-1)
[🔗](#lib:operator=,pair______)
`template<class U1, class U2> constexpr pair& operator=(pair<U1, U2>&& p);
`
[39](#pair-39)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1146)
*Constraints*:
- [(39.1)](#pair-39.1)
is_assignable_v<T1&, U1> is true and
- [(39.2)](#pair-39.2)
is_assignable_v<T2&, U2> is true[.](#pair-39.sentence-1)
[40](#pair-40)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1153)
*Effects*: Assigns std::forward<U1>(p.first) first andstd::forward<U2>(p.second) to second[.](#pair-40.sentence-1)
[41](#pair-41)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1158)
*Returns*: *this[.](#pair-41.sentence-1)
[🔗](#lib:operator=,pair_______)
`template<[pair-like](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]") P> constexpr pair& operator=(P&& p);
`
[42](#pair-42)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1169)
*Constraints*:
- [(42.1)](#pair-42.1)
[*different-from*](range.utility.helpers#concept:different-from "25.5.2Helper concepts[range.utility.helpers]")<P, pair> ([[range.utility.helpers]](range.utility.helpers "25.5.2Helper concepts"))
is true,
- [(42.2)](#pair-42.2)
remove_cvref_t<P> is not a specialization of ranges::subrange,
- [(42.3)](#pair-42.3)
is_assignable_v<T1&, decltype(get<0>(std::forward<P>(p)))> is true, and
- [(42.4)](#pair-42.4)
is_assignable_v<T2&, decltype(get<1>(std::forward<P>(p)))> is true[.](#pair-42.sentence-1)
[43](#pair-43)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1185)
*Effects*: Assigns get<0>(std::forward<P>(p)) to first andget<1>(std::forward<P>(p)) to second[.](#pair-43.sentence-1)
[44](#pair-44)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1190)
*Returns*: *this[.](#pair-44.sentence-1)
[🔗](#lib:operator=,pair________)
`template<[pair-like](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]") P> constexpr const pair& operator=(P&& p) const;
`
[45](#pair-45)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1201)
*Constraints*:
- [(45.1)](#pair-45.1)
[*different-from*](range.utility.helpers#concept:different-from "25.5.2Helper concepts[range.utility.helpers]")<P, pair> ([[range.utility.helpers]](range.utility.helpers "25.5.2Helper concepts"))
is true,
- [(45.2)](#pair-45.2)
remove_cvref_t<P> is not a specialization of ranges::subrange,
- [(45.3)](#pair-45.3)
is_assignable_v<const T1&, decltype(get<0>(std::forward<P>(p)))> is true, and
- [(45.4)](#pair-45.4)
is_assignable_v<const T2&, decltype(get<1>(std::forward<P>(p)))> is true[.](#pair-45.sentence-1)
[46](#pair-46)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1217)
*Effects*: Assigns get<0>(std::forward<P>(p)) to first andget<1>(std::forward<P>(p)) to second[.](#pair-46.sentence-1)
[47](#pair-47)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1222)
*Returns*: *this[.](#pair-47.sentence-1)
[🔗](#lib:operator=,pair_________)
`template<class U1, class U2> constexpr const pair& operator=(pair<U1, U2>&& p) const;
`
[48](#pair-48)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1233)
*Constraints*:
- [(48.1)](#pair-48.1)
is_assignable_v<const T1&, U1> is true, and
- [(48.2)](#pair-48.2)
is_assignable_v<const T2&, U2> is true[.](#pair-48.sentence-1)
[49](#pair-49)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1242)
*Effects*: Assigns std::forward<U1>(p.first) to first andstd::forward<U2>(u.second) to second[.](#pair-49.sentence-1)
[50](#pair-50)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1247)
*Returns*: *this[.](#pair-50.sentence-1)
[🔗](#lib:swap,pair)
`constexpr void swap(pair& p) noexcept(see below);
constexpr void swap(const pair& p) const noexcept(see below);
`
[51](#pair-51)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1259)
*Mandates*:
- [(51.1)](#pair-51.1)
For the first overload,is_swappable_v<T1> is true andis_swappable_v<T2> is true[.](#pair-51.1.sentence-1)
- [(51.2)](#pair-51.2)
For the second overload,is_swappable_v<const T1> is true andis_swappable_v<const T2> is true[.](#pair-51.2.sentence-1)
[52](#pair-52)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1272)
*Preconditions*: first is swappable with ([[swappable.requirements]](swappable.requirements "16.4.4.3Swappable requirements")) p.first andsecond is swappable with p.second[.](#pair-52.sentence-1)
[53](#pair-53)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1277)
*Effects*: Swapsfirst with p.first andsecond with p.second[.](#pair-53.sentence-1)
[54](#pair-54)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1283)
*Remarks*: The exception specification is equivalent to:
- [(54.1)](#pair-54.1)
is_nothrow_swappable_v<T1> && is_nothrow_swappable_v<T2> for the first overload, and
- [(54.2)](#pair-54.2)
is_nothrow_swappable_v<const T1> && is_nothrow_swappable_v<const T2> for the second overload[.](#pair-54.sentence-1)
### [22.3.3](#spec) Specialized algorithms [[pairs.spec]](pairs.spec)
[🔗](#lib:operator==,pair)
`template<class T1, class T2, class U1, class U2>
constexpr bool operator==(const pair<T1, T2>& x, const pair<U1, U2>& y);
`
[1](#spec-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1305)
*Constraints*: x.first == y.first and x.second == y.second are
valid expressions and
each of decltype(x.first == y.first) anddecltype(x.second == y.second) models *boolean-
testable*[.](#spec-1.sentence-1)
[2](#spec-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1312)
*Returns*: x.first == y.first && x.second == y.second[.](#spec-2.sentence-1)
[🔗](#lib:operator%3c=%3e,pair)
`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<U1, U2>& y);
`
[3](#spec-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1326)
*Effects*: Equivalent to:if (auto c = *synth-three-way*(x.first, y.first); c != 0) return c;return *synth-three-way*(x.second, y.second);
[🔗](#lib:swap,pair_)
`template<class T1, class T2>
constexpr void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
template<class T1, class T2>
constexpr void swap(const pair<T1, T2>& x, const pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
`
[4](#spec-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1344)
*Constraints*:
- [(4.1)](#spec-4.1)
For the first overload,is_swappable_v<T1> is true andis_swappable_v<T2> is true[.](#spec-4.1.sentence-1)
- [(4.2)](#spec-4.2)
For the second overload,is_swappable_v<const T1> is true andis_swappable_v<const T2> is true[.](#spec-4.2.sentence-1)
[5](#spec-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1357)
*Effects*: Equivalent to x.swap(y)[.](#spec-5.sentence-1)
[🔗](#lib:make_pair)
`template<class T1, class T2>
constexpr pair<unwrap_ref_decay_t<T1>, unwrap_ref_decay_t<T2>> make_pair(T1&& x, T2&& y);
`
[6](#spec-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1369)
*Returns*: pair<unwrap_ref_decay_t<T1>,
unwrap_ref_decay_t<T2>>(std::forward<T1>(x), std::forward<T2>(y))
[7](#spec-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1377)
[*Example [1](#spec-example-1)*:
In place of:return pair<int, double>(5, 3.1415926); // explicit types a C++ program may contain:return make_pair(5, 3.1415926); // types are deduced
— *end example*]
### [22.3.4](#pair.astuple) Tuple-like access to pair [[pair.astuple]](pair.astuple)
[🔗](#lib:tuple_size)
`template<class T1, class T2>
struct tuple_size<pair<T1, T2>> : integral_constant<size_t, 2> { };
`
[🔗](#lib:tuple_element)
`template<size_t I, class T1, class T2>
struct tuple_element<I, pair<T1, T2>> {
using type = see below ;
};
`
[1](#pair.astuple-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1405)
*Mandates*: I<2[.](#pair.astuple-1.sentence-1)
[2](#pair.astuple-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1409)
*Type*: The type T1 if I is 0, otherwise the type T2[.](#pair.astuple-2.sentence-1)
[🔗](#lib:get,pair)
`template<size_t I, class T1, class T2>
constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>& p) noexcept;
template<size_t I, class T1, class T2>
constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>& p) noexcept;
template<size_t I, class T1, class T2>
constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&& p) noexcept;
template<size_t I, class T1, class T2>
constexpr const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&& p) noexcept;
`
[3](#pair.astuple-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1427)
*Mandates*: I<2[.](#pair.astuple-3.sentence-1)
[4](#pair.astuple-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1431)
*Returns*:
- [(4.1)](#pair.astuple-4.1)
If I is 0, returns a reference to p.first[.](#pair.astuple-4.1.sentence-1)
- [(4.2)](#pair.astuple-4.2)
If I is 1, returns a reference to p.second[.](#pair.astuple-4.2.sentence-1)
[🔗](#lib:get,pair_)
`template<class T1, class T2>
constexpr T1& get(pair<T1, T2>& p) noexcept;
template<class T1, class T2>
constexpr const T1& get(const pair<T1, T2>& p) noexcept;
template<class T1, class T2>
constexpr T1&& get(pair<T1, T2>&& p) noexcept;
template<class T1, class T2>
constexpr const T1&& get(const pair<T1, T2>&& p) noexcept;
`
[5](#pair.astuple-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1455)
*Mandates*: T1 and T2 are distinct types[.](#pair.astuple-5.sentence-1)
[6](#pair.astuple-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1459)
*Returns*: A reference to p.first[.](#pair.astuple-6.sentence-1)
[🔗](#lib:get,pair__)
`template<class T2, class T1>
constexpr T2& get(pair<T1, T2>& p) noexcept;
template<class T2, class T1>
constexpr const T2& get(const pair<T1, T2>& p) noexcept;
template<class T2, class T1>
constexpr T2&& get(pair<T1, T2>&& p) noexcept;
template<class T2, class T1>
constexpr const T2&& get(const pair<T1, T2>&& p) noexcept;
`
[7](#pair.astuple-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1477)
*Mandates*: T1 and T2 are distinct types[.](#pair.astuple-7.sentence-1)
[8](#pair.astuple-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1481)
*Returns*: A reference to p.second[.](#pair.astuple-8.sentence-1)
### [22.3.5](#pair.piecewise) Piecewise construction [[pair.piecewise]](pair.piecewise)
[🔗](#lib:piecewise_construct_t)
`struct piecewise_construct_t {
explicit piecewise_construct_t() = default;
};
inline constexpr piecewise_construct_t piecewise_construct{};
`
[1](#pair.piecewise-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L1497)
The struct piecewise_construct_t is an empty class type
used as a unique type to disambiguate constructor and function overloading[.](#pair.piecewise-1.sentence-1)
Specifically,pair has a constructor with piecewise_construct_t as the
first argument, immediately followed by two <tuple> arguments used
for piecewise construction of the elements of the pair object[.](#pair.piecewise-1.sentence-2)