19 General utilities library [utilities]

19.4 Pairs [pairs]

19.4.1 In general [pairs.general]

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

19.4.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;
    explicit(see below) constexpr pair();
    explicit(see below) constexpr pair(const T1& x, const T2& y);
    template<class U1, class U2>
      explicit(see below) constexpr pair(U1&& x, U2&& y);
    template<class U1, class U2>
      explicit(see below) constexpr pair(const pair<U1, U2>& p);
    template<class U1, class U2>
      explicit(see below) constexpr pair(pair<U1, U2>&& p);
    template<class... Args1, class... Args2>
      pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args);

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

    void swap(pair& p) noexcept(see below);
  };

  template<class T1, class T2>
    pair(T1, T2) -> pair<T1, T2>;
}
Constructors and member functions of pair shall not throw exceptions unless one of the element-wise operations specified to be called for that operation throws an exception.
The defaulted move and copy constructor, respectively, of pair shall be a constexpr function if and only if all required element-wise initializations for copy and move, respectively, would satisfy the requirements for a constexpr function.
If (is_­trivially_­destructible_­v<T1> && is_­trivially_­destructible_­v<T2>) is true, then the destructor of pair is trivial.
explicit(see below) constexpr pair();
Effects: Value-initializes first and second.
Remarks: This constructor shall not participate in overload resolution unless is_­default_­constructible_­v<first_­type> is true and is_­default_­constructible_­v<second_­type> is true.
[ Note
:
This behavior can be implemented by a constructor template with default template arguments.
— end note
 ]
The expression inside explicit evaluates to true if and only if either first_­type or second_­type is not implicitly default-constructible.
[ Note
:
This behavior can be implemented with a trait that checks whether a const first_­type& or a const second_­type& can be initialized with {}.
— end note
 ]
explicit(see below) constexpr pair(const T1& x, const T2& y);
Effects: Initializes first with x and second with y.
Remarks: This constructor shall not participate in overload resolution unless is_­copy_­constructible_­v<first_­type> is true and is_­copy_­constructible_­v<second_­type> is true.
The expression inside explicit is equivalent to:
!is_convertible_v<const first_type&, first_type> ||
  !is_convertible_v<const second_type&, second_type>
template<class U1, class U2> explicit(see below) constexpr pair(U1&& x, U2&& y);
Effects: Initializes first with std​::​forward<U1>(x) and second with std​::​forward<U2>(y).
Remarks: This constructor shall not participate in overload resolution unless is_­constructible_­v<first_­type, U1&&> is true and is_­constructible_­v<second_­type, U2&&> is true.
The expression inside explicit is equivalent to:
!is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
template<class U1, class U2> explicit(see below) constexpr pair(const pair<U1, U2>& p);
Effects: Initializes members from the corresponding members of the argument.
Remarks: This constructor shall not participate in overload resolution unless is_­constructible_­v<first_­type, const U1&> is true and is_­constructible_­v<second_­type, const U2&> is true.
The expression inside explicit is equivalent to:
!is_convertible_v<const U1&, first_type> || !is_convertible_v<const U2&, second_type>
template<class U1, class U2> explicit(see below) constexpr pair(pair<U1, U2>&& p);
Effects: Initializes first with std​::​forward<U1>(p.first) and second with std​::​forward<U2>(​p.second).
Remarks: This constructor shall not participate in overload resolution unless is_­constructible_­v<first_­type, U1&&> is true and is_­constructible_­v<second_­type, U2&&> is true.
The expression inside explicit is equivalent to:
!is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
template<class... Args1, class... Args2> pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args);
Requires: is_­constructible_­v<first_­type, Args1&&...> is true and is_­constructible_­v<second_­type, Args2&&...> is true.
Effects: Initializes first with arguments of types Args1... 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 calling std​::​forward<U>(x).)
This form of construction, whereby constructor arguments for first and second are each provided in a separate tuple object, is called piecewise construction.
pair& operator=(const pair& p);
Effects: Assigns p.first to first and p.second to second.
Remarks: This operator shall be defined as deleted unless is_­copy_­assignable_­v<first_­type> is true and is_­copy_­assignable_­v<second_­type> is true.
Returns: *this.
template<class U1, class U2> pair& operator=(const pair<U1, U2>& p);
Effects: Assigns p.first to first and p.second to second.
Remarks: This operator shall not participate in overload resolution unless is_­assignable_­v<first_­type&, const U1&> is true and is_­assignable_­v<second_­type&, const U2&> is true.
Returns: *this.
pair& operator=(pair&& p) noexcept(see below);
Effects: Assigns to first with std​::​forward<first_­type>(p.first) and to second with
std​::​forward<second_­type>(p.second).
Remarks: This operator shall not participate in overload resolution unless is_­move_­assignable_­v<first_­type> is true and is_­move_­assignable_­v<second_­type> is true.
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_assignable_v<T1> && is_nothrow_move_assignable_v<T2>
Returns: *this.
template<class U1, class U2> pair& operator=(pair<U1, U2>&& p);
Effects: Assigns to first with std​::​forward<U1>(p.first) and to second with
std​::​forward<U2>(p.second).
Remarks: This operator shall not participate in overload resolution unless is_­assignable_­v<first_­type&, U1&&> is true and is_­assignable_­v<second_­type&, U2&&> is true.
Returns: *this.
void swap(pair& p) noexcept(see below);
Requires: first shall be swappable with ([swappable.requirements]) p.first and second shall be swappable with p.second.
Effects: Swaps first with p.first and second with p.second.
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_swappable_v<first_type> && is_nothrow_swappable_v<second_type>

19.4.3 Specialized algorithms [pairs.spec]

template<class T1, class T2> constexpr bool operator==(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: x.first == y.first && x.second == y.second.
template<class T1, class T2> constexpr bool operator!=(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: !(x == y).
template<class T1, class T2> constexpr bool operator<(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: x.first < y.first || (!(y.first < x.first) && x.second < y.second).
template<class T1, class T2> constexpr bool operator>(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: y < x.
template<class T1, class T2> constexpr bool operator<=(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: !(y < x).
template<class T1, class T2> constexpr bool operator>=(const pair<T1, T2>& x, const pair<T1, T2>& y);
Returns: !(x < y).
template<class T1, class T2> void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
Effects: As if by x.swap(y).
Remarks: This function shall not participate in overload resolution unless is_­swappable_­v<T1> is true and is_­swappable_­v<T2> is true.
template<class T1, class T2> constexpr pair<V1, V2> make_pair(T1&& x, T2&& y);
Returns: pair<V1, V2>(std​::​forward<T1>(x), std​::​forward<T2>(y)), where V1 and V2 are determined as follows: Let Ui be decay_­t<Ti> for each Ti.
If Ui is a specialization of reference_­wrapper, then Vi is Ui​::​type&, otherwise Vi is Ui.
[ Example
:
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
 ]

19.4.4 Tuple-like access to pair [pair.astuple]

template<class T1, class T2> struct tuple_size<pair<T1, T2>> : integral_constant<size_t, 2> { };
tuple_element<I, pair<T1, T2>>::type
Requires: I < 2.
The program is ill-formed if I is out of bounds.
Value: The type T1 if I == 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;
Returns: If I == 0 returns a reference to p.first; if I == 1 returns a reference to p.second; otherwise the program is ill-formed.
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;
Requires: T1 and T2 are distinct types.
Otherwise, the program is ill-formed.
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;
Requires: T1 and T2 are distinct types.
Otherwise, the program is ill-formed.
Returns: A reference to p.second.

19.4.5 Piecewise construction [pair.piecewise]

struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; inline constexpr piecewise_construct_t piecewise_construct{};
The struct piecewise_­construct_­t is an empty structure 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 tuple arguments used for piecewise construction of the elements of the pair object.