Files
cppdraft_translate/cppdraft/pairs.md
2025-10-25 03:02:53 +03:00

28 KiB
Raw Blame History

[pairs]

22 General utilities library [utilities]

22.3 Pairs [pairs]

22.3.1 General [pairs.general]

1

#

The library provides a template for heterogeneous pairs of values.

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] and [tuple.elem]).

22.3.2 Class template pair [pairs.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); templateconstexpr 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 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 P>constexpr pair& operator=(P&& p); template<pair-like 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

#

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.

2

#

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]).

3

#

If (is_trivially_destructible_v && is_trivially_destructible_v) is true, then the destructor of pair is trivial.

4

#

pair<T, U> is a structural type ([temp.param]) if T and U are both structural types.

Two values p1 and p2 of type pair<T, U> are template-argument-equivalent ([temp.type]) if and only ifp1.first and p2.first are template-argument-equivalent andp1.second and p2.second are template-argument-equivalent.

🔗

constexpr explicit(see below) pair();

5

#

Constraints:

is_default_constructible_v is true and

is_default_constructible_v is true.

6

#

Effects: Value-initializes first and second.

7

#

Remarks: The expression inside explicit evaluates to true if and only if either T1 orT2 is not implicitly default-constructible.

[Note 1:

This behavior can be implemented with a trait that checks whether a const T1& or a const T2& can be initialized with {}.

— end note]

🔗

constexpr explicit(see below) pair(const T1& x, const T2& y);

8

#

Constraints:

is_copy_constructible_v is true and

is_copy_constructible_v is true.

9

#

Effects: Initializes first with x and second with y.

10

#

Remarks: The expression inside explicit is equivalent to:!is_convertible_v<const T1&, T1> || !is_convertible_v<const T2&, T2>

🔗

template<class U1 = T1, class U2 = T2> constexpr explicit(see below) pair(U1&& x, U2&& y);

11

#

Constraints:

is_constructible_v<T1, U1> is true and

is_constructible_v<T2, U2> is true.

12

#

Effects: Initializes first withstd::forward(x) and second with std::forward(y).

13

#

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.

🔗

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

#

Let FWD(u) be static_cast<decltype(u)>(u).

15

#

Constraints:

For the last overload,remove_cvref_t

is not a specialization of ranges::subrange,

is_constructible_v<T1, decltype(get<0>(FWD(p)))> is true, and

is_constructible_v<T2, decltype(get<1>(FWD(p)))> is true.

16

#

Effects: Initializes first with get<0>(FWD(p)) andsecond with get<1>(FWD(p)).

17

#

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.

🔗

template<class... Args1, class... Args2> constexpr pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args);

18

#

Mandates:

is_constructible_v<T1, Args1...> is true and

is_constructible_v<T2, Args2...> is true.

19

#

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.

(Here, forwarding an element x of type U within a tuple object means callingstd::forward(x).)

This form of construction, whereby constructor arguments for first and second are each provided in a separatetuple object, is called piecewise construction.

[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]).

— end note]

🔗

constexpr pair& operator=(const pair& p);

20

#

Effects: Assigns p.first to first and p.second to second.

21

#

Returns: *this.

22

#

Remarks: This operator is defined as deleted unlessis_copy_assignable_v is true andis_copy_assignable_v is true.

🔗

constexpr const pair& operator=(const pair& p) const;

23

#

Constraints:

is_copy_assignable_v is true and

is_copy_assignable_v is true.

24

#

Effects: Assigns p.first to first and p.second to second.

25

#

Returns: *this.

🔗

template<class U1, class U2> constexpr pair& operator=(const pair<U1, U2>& p);

26

#

Constraints:

is_assignable_v<T1&, const U1&> is true and

is_assignable_v<T2&, const U2&> is true.

27

#

Effects: Assigns p.first to first and p.second to second.

28

#

Returns: *this.

🔗

template<class U1, class U2> constexpr const pair& operator=(const pair<U1, U2>& p) const;

29

#

Constraints:

is_assignable_v<const T1&, const U1&> is true, and

is_assignable_v<const T2&, const U2&> is true.

30

#

Effects: Assigns p.first to first and p.second to second.

31

#

Returns: *this.

🔗

constexpr pair& operator=(pair&& p) noexcept(see below);

32

#

Constraints:

is_move_assignable_v is true and

is_move_assignable_v is true.

33

#

Effects: Assigns std::forward(p.first) to first andstd::forward(p.second) to second.

34

#

Returns: *this.

35

#

Remarks: The exception specification is equivalent to:is_nothrow_move_assignable_v && is_nothrow_move_assignable_v

🔗

constexpr const pair& operator=(pair&& p) const;

36

#

Constraints:

is_assignable_v<const T1&, T1> is true and

is_assignable_v<const T2&, T2> is true.

37

#

Effects: Assigns std::forward(p.first) to first andstd::forward(p.second) to second.

38

#

Returns: *this.

🔗

template<class U1, class U2> constexpr pair& operator=(pair<U1, U2>&& p);

39

#

Constraints:

is_assignable_v<T1&, U1> is true and

is_assignable_v<T2&, U2> is true.

40

#

Effects: Assigns std::forward(p.first) first andstd::forward(p.second) to second.

41

#

Returns: *this.

🔗

template<[pair-like](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]") P> constexpr pair& operator=(P&& p);

42

#

Constraints:

different-from<P, pair> ([range.utility.helpers]) is true,

remove_cvref_t

is not a specialization of ranges::subrange,

is_assignable_v<T1&, decltype(get<0>(std::forward

(p)))> is true, and

is_assignable_v<T2&, decltype(get<1>(std::forward

(p)))> is true.

43

#

Effects: Assigns get<0>(std::forward

(p)) to first andget<1>(std::forward

(p)) to second.

44

#

Returns: *this.

🔗

template<[pair-like](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]") P> constexpr const pair& operator=(P&& p) const;

45

#

Constraints:

different-from<P, pair> ([range.utility.helpers]) is true,

remove_cvref_t

is not a specialization of ranges::subrange,

is_assignable_v<const T1&, decltype(get<0>(std::forward

(p)))> is true, and

is_assignable_v<const T2&, decltype(get<1>(std::forward

(p)))> is true.

46

#

Effects: Assigns get<0>(std::forward

(p)) to first andget<1>(std::forward

(p)) to second.

47

#

Returns: *this.

🔗

template<class U1, class U2> constexpr const pair& operator=(pair<U1, U2>&& p) const;

48

#

Constraints:

is_assignable_v<const T1&, U1> is true, and

is_assignable_v<const T2&, U2> is true.

49

#

Effects: Assigns std::forward(p.first) to first andstd::forward(u.second) to second.

50

#

Returns: *this.

🔗

constexpr void swap(pair& p) noexcept(see below); constexpr void swap(const pair& p) const noexcept(see below);

51

#

Mandates:

  • (51.1)

    For the first overload,is_swappable_v is true andis_swappable_v is true.

  • (51.2)

    For the second overload,is_swappable_v is true andis_swappable_v is true.

52

#

Preconditions: first is swappable with ([swappable.requirements]) p.first andsecond is swappable with p.second.

53

#

Effects: Swapsfirst with p.first andsecond with p.second.

54

#

Remarks: The exception specification is equivalent to:

is_nothrow_swappable_v && is_nothrow_swappable_v for the first overload, and

is_nothrow_swappable_v && is_nothrow_swappable_v for the second overload.

22.3.3 Specialized algorithms [pairs.spec]

🔗

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

1

#

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
.

2

#

Returns: x.first == y.first && x.second == y.second.

🔗

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

#

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);

🔗

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

#

Constraints:

  • (4.1)

    For the first overload,is_swappable_v is true andis_swappable_v is true.

  • (4.2)

    For the second overload,is_swappable_v is true andis_swappable_v is true.

5

#

Effects: Equivalent to x.swap(y).

🔗

template<class T1, class T2> constexpr pair<unwrap_ref_decay_t<T1>, unwrap_ref_decay_t<T2>> make_pair(T1&& x, T2&& y);

6

#

Returns: pair<unwrap_ref_decay_t, unwrap_ref_decay_t>(std::forward(x), std::forward(y))

7

#

[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 Tuple-like access to pair [pair.astuple]

🔗

template<class T1, class T2> struct tuple_size<pair<T1, T2>> : integral_constant<size_t, 2> { };

🔗

template<size_t I, class T1, class T2> struct tuple_element<I, pair<T1, T2>> { using type = see below ; };

1

#

Mandates: I<2.

2

#

Type: The type T1 if I is 0, otherwise the type T2.

🔗

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

#

Mandates: I<2.

4

#

Returns:

  • (4.1)

    If I is 0, returns a reference to p.first.

  • (4.2)

    If I is 1, returns a reference to p.second.

🔗

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

#

Mandates: T1 and T2 are distinct types.

6

#

Returns: A reference to p.first.

🔗

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

#

Mandates: T1 and T2 are distinct types.

8

#

Returns: A reference to p.second.

22.3.5 Piecewise construction [pair.piecewise]

🔗

struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; inline constexpr piecewise_construct_t piecewise_construct{};

1

#

The struct piecewise_construct_t is an empty class type used as a unique type to disambiguate constructor and function overloading.

Specifically,pair has a constructor with piecewise_construct_t as the first argument, immediately followed by two arguments used for piecewise construction of the elements of the pair object.