275 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___CXX03___UTILITY_PAIR_H10#define _LIBCPP___CXX03___UTILITY_PAIR_H11 12#include <__cxx03/__config>13#include <__cxx03/__fwd/array.h>14#include <__cxx03/__fwd/pair.h>15#include <__cxx03/__fwd/tuple.h>16#include <__cxx03/__tuple/sfinae_helpers.h>17#include <__cxx03/__tuple/tuple_element.h>18#include <__cxx03/__tuple/tuple_indices.h>19#include <__cxx03/__tuple/tuple_like_no_subrange.h>20#include <__cxx03/__tuple/tuple_size.h>21#include <__cxx03/__type_traits/common_type.h>22#include <__cxx03/__type_traits/conditional.h>23#include <__cxx03/__type_traits/decay.h>24#include <__cxx03/__type_traits/integral_constant.h>25#include <__cxx03/__type_traits/is_assignable.h>26#include <__cxx03/__type_traits/is_constructible.h>27#include <__cxx03/__type_traits/is_convertible.h>28#include <__cxx03/__type_traits/is_implicitly_default_constructible.h>29#include <__cxx03/__type_traits/is_nothrow_assignable.h>30#include <__cxx03/__type_traits/is_nothrow_constructible.h>31#include <__cxx03/__type_traits/is_reference.h>32#include <__cxx03/__type_traits/is_same.h>33#include <__cxx03/__type_traits/is_swappable.h>34#include <__cxx03/__type_traits/is_trivially_relocatable.h>35#include <__cxx03/__type_traits/nat.h>36#include <__cxx03/__type_traits/remove_cvref.h>37#include <__cxx03/__type_traits/unwrap_ref.h>38#include <__cxx03/__utility/declval.h>39#include <__cxx03/__utility/forward.h>40#include <__cxx03/__utility/move.h>41#include <__cxx03/__utility/piecewise_construct.h>42#include <__cxx03/cstddef>43 44#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)45# pragma GCC system_header46#endif47 48_LIBCPP_PUSH_MACROS49#include <__cxx03/__undef_macros>50 51_LIBCPP_BEGIN_NAMESPACE_STD52 53template <class, class>54struct __non_trivially_copyable_base {55 _LIBCPP_HIDE_FROM_ABI __non_trivially_copyable_base() _NOEXCEPT {}56 _LIBCPP_HIDE_FROM_ABI __non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {}57};58 59template <class _T1, class _T2>60struct _LIBCPP_TEMPLATE_VIS pair61#if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR)62 : private __non_trivially_copyable_base<_T1, _T2>63#endif64{65 using first_type = _T1;66 using second_type = _T2;67 68 _T1 first;69 _T2 second;70 71 using __trivially_relocatable =72 __conditional_t<__libcpp_is_trivially_relocatable<_T1>::value && __libcpp_is_trivially_relocatable<_T2>::value,73 pair,74 void>;75 76 _LIBCPP_HIDE_FROM_ABI pair(pair const&) = default;77 _LIBCPP_HIDE_FROM_ABI pair(pair&&) = default;78 79 // When we are requested for pair to be trivially copyable by the ABI macro, we use defaulted members80 // if it is both legal to do it (i.e. no references) and we have a way to actually implement it, which requires81 // the __enable_if__ attribute before C++20.82#ifdef _LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR83 // FIXME: This should really just be a static constexpr variable. It's in a struct to avoid gdb printing the value84 // when printing a pair85 struct __has_defaulted_members {86 static const bool value = !is_reference<first_type>::value && !is_reference<second_type>::value;87 };88# if __has_attribute(__enable_if__)89 _LIBCPP_HIDE_FROM_ABI pair& operator=(const pair&)90 __attribute__((__enable_if__(__has_defaulted_members::value, ""))) = default;91 92 _LIBCPP_HIDE_FROM_ABI pair& operator=(pair&&)93 __attribute__((__enable_if__(__has_defaulted_members::value, ""))) = default;94# else95# error "_LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR isn't supported with this compiler"96# endif97#else98 struct __has_defaulted_members {99 static const bool value = false;100 };101#endif // defined(_LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR) && __has_attribute(__enable_if__)102 103 _LIBCPP_HIDE_FROM_ABI pair() : first(), second() {}104 105 _LIBCPP_HIDE_FROM_ABI pair(_T1 const& __t1, _T2 const& __t2) : first(__t1), second(__t2) {}106 107 template <class _U1, class _U2>108 _LIBCPP_HIDE_FROM_ABI pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {}109 110 _LIBCPP_HIDE_FROM_ABI pair& operator=(pair const& __p) {111 first = __p.first;112 second = __p.second;113 return *this;114 }115 116 // Extension: This is provided in C++03 because it allows properly handling the117 // assignment to a pair containing references, which would be a hard118 // error otherwise.119 template <120 class _U1,121 class _U2,122 __enable_if_t<is_assignable<first_type&, _U1 const&>::value && is_assignable<second_type&, _U2 const&>::value,123 int> = 0>124 _LIBCPP_HIDE_FROM_ABI pair& operator=(pair<_U1, _U2> const& __p) {125 first = __p.first;126 second = __p.second;127 return *this;128 }129 130 _LIBCPP_HIDE_FROM_ABI void swap(pair& __p) {131 using std::swap;132 swap(first, __p.first);133 swap(second, __p.second);134 }135};136 137// [pairs.spec], specialized algorithms138 139template <class _T1, class _T2, class _U1, class _U2>140inline _LIBCPP_HIDE_FROM_ABI bool operator==(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {141 return __x.first == __y.first && __x.second == __y.second;142}143 144template <class _T1, class _T2, class _U1, class _U2>145inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {146 return !(__x == __y);147}148 149template <class _T1, class _T2, class _U1, class _U2>150inline _LIBCPP_HIDE_FROM_ABI bool operator<(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {151 return __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second);152}153 154template <class _T1, class _T2, class _U1, class _U2>155inline _LIBCPP_HIDE_FROM_ABI bool operator>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {156 return __y < __x;157}158 159template <class _T1, class _T2, class _U1, class _U2>160inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {161 return !(__x < __y);162}163 164template <class _T1, class _T2, class _U1, class _U2>165inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {166 return !(__y < __x);167}168 169template <class _T1, class _T2, __enable_if_t<__is_swappable_v<_T1> && __is_swappable_v<_T2>, int> = 0>170inline _LIBCPP_HIDE_FROM_ABI void swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) {171 __x.swap(__y);172}173 174template <class _T1, class _T2>175inline _LIBCPP_HIDE_FROM_ABI pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type>176make_pair(_T1&& __t1, _T2&& __t2) {177 return pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type>(178 std::forward<_T1>(__t1), std::forward<_T2>(__t2));179}180 181template <class _T1, class _T2>182struct _LIBCPP_TEMPLATE_VIS tuple_size<pair<_T1, _T2> > : public integral_constant<size_t, 2> {};183 184template <size_t _Ip, class _T1, class _T2>185struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, pair<_T1, _T2> > {186 static_assert(_Ip < 2, "Index out of bounds in std::tuple_element<std::pair<T1, T2>>");187};188 189template <class _T1, class _T2>190struct _LIBCPP_TEMPLATE_VIS tuple_element<0, pair<_T1, _T2> > {191 using type _LIBCPP_NODEBUG = _T1;192};193 194template <class _T1, class _T2>195struct _LIBCPP_TEMPLATE_VIS tuple_element<1, pair<_T1, _T2> > {196 using type _LIBCPP_NODEBUG = _T2;197};198 199template <size_t _Ip>200struct __get_pair;201 202template <>203struct __get_pair<0> {204 template <class _T1, class _T2>205 static _LIBCPP_HIDE_FROM_ABI _T1& get(pair<_T1, _T2>& __p) _NOEXCEPT {206 return __p.first;207 }208 209 template <class _T1, class _T2>210 static _LIBCPP_HIDE_FROM_ABI const _T1& get(const pair<_T1, _T2>& __p) _NOEXCEPT {211 return __p.first;212 }213 214 template <class _T1, class _T2>215 static _LIBCPP_HIDE_FROM_ABI _T1&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {216 return std::forward<_T1>(__p.first);217 }218 219 template <class _T1, class _T2>220 static _LIBCPP_HIDE_FROM_ABI const _T1&& get(const pair<_T1, _T2>&& __p) _NOEXCEPT {221 return std::forward<const _T1>(__p.first);222 }223};224 225template <>226struct __get_pair<1> {227 template <class _T1, class _T2>228 static _LIBCPP_HIDE_FROM_ABI _T2& get(pair<_T1, _T2>& __p) _NOEXCEPT {229 return __p.second;230 }231 232 template <class _T1, class _T2>233 static _LIBCPP_HIDE_FROM_ABI const _T2& get(const pair<_T1, _T2>& __p) _NOEXCEPT {234 return __p.second;235 }236 237 template <class _T1, class _T2>238 static _LIBCPP_HIDE_FROM_ABI _T2&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {239 return std::forward<_T2>(__p.second);240 }241 242 template <class _T1, class _T2>243 static _LIBCPP_HIDE_FROM_ABI const _T2&& get(const pair<_T1, _T2>&& __p) _NOEXCEPT {244 return std::forward<const _T2>(__p.second);245 }246};247 248template <size_t _Ip, class _T1, class _T2>249inline _LIBCPP_HIDE_FROM_ABI typename tuple_element<_Ip, pair<_T1, _T2> >::type& get(pair<_T1, _T2>& __p) _NOEXCEPT {250 return __get_pair<_Ip>::get(__p);251}252 253template <size_t _Ip, class _T1, class _T2>254inline _LIBCPP_HIDE_FROM_ABI const typename tuple_element<_Ip, pair<_T1, _T2> >::type&255get(const pair<_T1, _T2>& __p) _NOEXCEPT {256 return __get_pair<_Ip>::get(__p);257}258 259template <size_t _Ip, class _T1, class _T2>260inline _LIBCPP_HIDE_FROM_ABI typename tuple_element<_Ip, pair<_T1, _T2> >::type&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {261 return __get_pair<_Ip>::get(std::move(__p));262}263 264template <size_t _Ip, class _T1, class _T2>265inline _LIBCPP_HIDE_FROM_ABI const typename tuple_element<_Ip, pair<_T1, _T2> >::type&&266get(const pair<_T1, _T2>&& __p) _NOEXCEPT {267 return __get_pair<_Ip>::get(std::move(__p));268}269 270_LIBCPP_END_NAMESPACE_STD271 272_LIBCPP_POP_MACROS273 274#endif // _LIBCPP___CXX03___UTILITY_PAIR_H275