23 General utilities library [utilities]

23.4 Pairs [pairs]

23.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 constexpr pair();
      EXPLICIT constexpr pair(const T1& x, const T2& y);
      template<class U1, class U2> EXPLICIT constexpr pair(U1&& x, U2&& y);
      template<class U1, class U2> EXPLICIT constexpr pair(const pair<U1, U2>& p);
      template<class U1, class U2> EXPLICIT 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. The destructor of pair shall be a trivial destructor if (is_­trivially_­destructible_­v<T1> && is_­trivially_­destructible_­v<T2>) is true.

EXPLICIT 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 constructor is explicit 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 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 constructor is explicit if and only if is_­convertible_­v<const first_­type&, first_­type> is false or is_­convertible_­v<const second_­type&, second_­type> is false.

template<class U1, class U2> EXPLICIT 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 constructor is explicit if and only if is_­convertible_­v<U1&&, first_­type> is false or is_­convertible_­v<U2&&, second_­type> is false.

template<class U1, class U2> EXPLICIT 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 constructor is explicit if and only if is_­convertible_­v<const U1&, first_­type> is false or is_­convertible_­v<const U2&, second_­type> is false.

template<class U1, class U2> EXPLICIT 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 constructor is explicit if and only if is_­convertible_­v<U1&&, first_­type> is false or is_­convertible_­v<U2&&, second_­type> is false.

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 be defined as deleted 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<U>(p.first) and to second with
std​::​forward<V>(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 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>