20 General utilities library [utilities]

20.4 Pairs [pairs]

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

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

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

  template<class T1, class T2>
    pair(T1, T2) -> pair<T1, T2>;
}
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.
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 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.
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 if p1.first and p2.first are template-argument-equivalent and p1.second and p2.second are template-argument-equivalent.
constexpr explicit(see below) pair();
Constraints:
  • is_­default_­constructible_­v<first_­type> is true and
  • is_­default_­constructible_­v<second_­type> is true.
Effects: Value-initializes first and second.
Remarks: 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
]
constexpr explicit(see below) pair(const T1& x, const T2& y);
Constraints:
  • is_­copy_­constructible_­v<first_­type> is true and
  • is_­copy_­constructible_­v<second_­type> is true.
Effects: Initializes first with x and second with y.
Remarks: 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> constexpr explicit(see below) pair(U1&& x, U2&& y);
Constraints:
  • is_­constructible_­v<first_­type, U1> is true and
  • is_­constructible_­v<second_­type, U2> is true.
Effects: Initializes first with std​::​forward<U1>(x) and second with std​::​forward<U2>(y).
Remarks: The expression inside explicit is equivalent to:
!is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>& p);
Constraints:
  • is_­constructible_­v<first_­type, const U1&> is true and
  • is_­constructible_­v<second_­type, const U2&> is true.
Effects: Initializes members from the corresponding members of the argument.
Remarks: 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> constexpr explicit(see below) pair(pair<U1, U2>&& p);
Constraints:
  • is_­constructible_­v<first_­type, U1> is true and
  • is_­constructible_­v<second_­type, U2> is true.
Effects: Initializes first with std​::​forward<U1>(p.first) and second with std​::​forward<U2>(​p.second).
Remarks: The expression inside explicit is equivalent to:
!is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
template<class... Args1, class... Args2> constexpr pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args);
Mandates:
  • 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.
constexpr pair& operator=(const pair& p);
Effects: Assigns p.first to first and p.second to second.
Remarks: This operator is 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> constexpr pair& operator=(const pair<U1, U2>& p);
Constraints:
  • is_­assignable_­v<first_­type&, const U1&> is true and
  • is_­assignable_­v<second_­type&, const U2&> is true.
Effects: Assigns p.first to first and p.second to second.
Returns: *this.
constexpr pair& operator=(pair&& p) noexcept(see below);
Constraints:
  • is_­move_­assignable_­v<first_­type> is true and
  • is_­move_­assignable_­v<second_­type> is true.
Effects: Assigns to first with std​::​forward<first_­type>(p.first) and to second with
std​::​forward<second_­type>(p.second).
Returns: *this.
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_assignable_v<T1> && is_nothrow_move_assignable_v<T2>
template<class U1, class U2> constexpr pair& operator=(pair<U1, U2>&& p);
Constraints:
  • is_­assignable_­v<first_­type&, U1> is true and
  • is_­assignable_­v<second_­type&, U2> is true.
Effects: Assigns to first with std​::​forward<U1>(p.first) and to second with
std​::​forward<U2>(p.second).
Returns: *this.
constexpr void swap(pair& p) noexcept(see below);
Preconditions: first is swappable with ([swappable.requirements]) p.first and second is 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>