1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef API_BASE_CONTAINERS_PAIR_H 17 #define API_BASE_CONTAINERS_PAIR_H 18 19 #include <base/containers/type_traits.h> 20 #include <base/namespace.h> 21 22 BASE_BEGIN_NAMESPACE() 23 template<class T1, class T2> 24 struct pair { 25 template<class U1 = T1, class U2 = T2, 26 enable_if_t<is_default_constructible_v<U1> && is_default_constructible_v<U2>, int> = 0> pairpair27 constexpr pair() noexcept(is_nothrow_default_constructible_v<U1>&& is_nothrow_default_constructible_v<U2>) 28 : first(), second() 29 {} 30 31 template<class U1 = T1, class U2 = T2, 32 enable_if_t<is_copy_constructible_v<U1> && is_copy_constructible_v<U2>, int> = 0> 33 constexpr 34 #if (__cplusplus == 202002L) 35 explicit(!(is_convertible_v<const U1&, U1> && is_convertible_v<const U2&, U2>)) 36 #endif pairpair37 pair(const T1& x, const T2& y) noexcept( 38 is_nothrow_copy_constructible_v<U1>&& is_nothrow_copy_constructible_v<U2>) 39 : first(x), second(y) 40 {} 41 42 template<class U1 = T1, class U2 = T2, 43 enable_if_t<is_constructible_v<T1, U1> && is_constructible_v<T2, U2>, int> = 0> 44 constexpr 45 #if (__cplusplus == 202002L) 46 explicit(!(is_convertible_v<U1, T1> && is_convertible_v<U2, T2>)) 47 #endif pairpair48 pair(U1&& x, U2&& y) noexcept(is_nothrow_constructible_v<T1, U1>&& is_nothrow_constructible_v<T2, U2>) 49 : first(BASE_NS::forward<U1>(x)), second(BASE_NS::forward<U2>(y)) 50 {} 51 52 template<class U1, class U2, 53 enable_if_t<is_constructible_v<T1, const U1&> && is_constructible_v<T2, const U2&>, int> = 0> 54 constexpr 55 #if (__cplusplus == 202002L) 56 explicit(!(is_convertible_v<const U1&, T1> && is_convertible_v<const U2&, T2>)) 57 #endif pairpair58 pair(const pair<U1, U2>& p) 59 : first(p.first), second(p.second) 60 {} 61 62 template<class U1, class U2, enable_if_t<is_constructible_v<T1, U1> && is_constructible_v<T2, U2>, int> = 0> 63 constexpr 64 #if (__cplusplus == 202002L) 65 explicit(!(is_convertible_v<U1, T1> && is_convertible_v<U2, T2>)) 66 #endif pairpair67 pair(pair<U1, U2>&& p) noexcept(is_nothrow_constructible_v<T1, U1>&& is_nothrow_constructible_v<T2, U2>) 68 : first(BASE_NS::forward<U1>(p.first)), second(BASE_NS::forward<U2>(p.second)) 69 {} 70 71 pair(const pair& other) = default; 72 73 pair(pair&& other) noexcept = default; 74 75 constexpr pair& operator=(const pair& other) 76 { 77 if (this != &other) { 78 first = other.first; 79 second = other.second; 80 } 81 return *this; 82 } 83 84 template<class U1, class U2, 85 enable_if_t<is_assignable_v<T1&, const U1&> && is_assignable_v<T2&, const U2&>, int> = 0> 86 constexpr pair& operator=(const pair<U1, U2>& other) 87 { 88 first = other.first; 89 second = other.second; 90 91 return *this; 92 } 93 94 constexpr pair& operator=(pair&& other) noexcept 95 { 96 if (this != &other) { 97 first = BASE_NS::move(other.first); 98 second = BASE_NS::move(other.second); 99 } 100 return *this; 101 } 102 103 template<class U1, class U2, enable_if_t<is_assignable_v<T1&, U1> && is_assignable_v<T2&, U2>, int> = 0> noexceptpair104 constexpr pair& operator=(pair<U1, U2>&& other) noexcept( 105 is_nothrow_constructible_v<T1, U1>&& is_nothrow_constructible_v<T2, U2>) 106 { 107 first = BASE_NS::forward<U1>(other.first); 108 second = BASE_NS::forward<U2>(other.second); 109 110 return *this; 111 } 112 113 using first_type = T1; 114 using second_type = T2; 115 first_type first; 116 second_type second; 117 }; 118 119 template<class T1, class T2> 120 pair(T1, T2) -> pair<T1, T2>; 121 122 template<class T1, class T2, class U1, class U2> 123 constexpr bool operator==(const BASE_NS::pair<T1, T2>& lhs, const BASE_NS::pair<U1, U2>& rhs) 124 { 125 return (lhs.first == rhs.first) && (lhs.second == rhs.second); 126 } 127 128 template<class T1, class T2, class U1, class U2> 129 constexpr bool operator!=(const BASE_NS::pair<T1, T2>& lhs, const BASE_NS::pair<U1, U2>& rhs) 130 { 131 return !(lhs == rhs); 132 } 133 134 template<class T1, class T2, class U1, class U2> 135 constexpr bool operator<(const BASE_NS::pair<T1, T2>& lhs, const BASE_NS::pair<U1, U2>& rhs) 136 { 137 if (lhs.first < rhs.first) { 138 return true; 139 } 140 if (rhs.first < lhs.first) { 141 return false; 142 } 143 if (lhs.second < rhs.second) { 144 return true; 145 } 146 return false; 147 } 148 149 template<class T1, class T2, class U1, class U2> 150 constexpr bool operator<=(const BASE_NS::pair<T1, T2>& lhs, const BASE_NS::pair<U1, U2>& rhs) 151 { 152 return !(rhs < lhs); 153 } 154 155 template<class T1, class T2, class U1, class U2> 156 constexpr bool operator>(const BASE_NS::pair<T1, T2>& lhs, const BASE_NS::pair<U1, U2>& rhs) 157 { 158 return (rhs < lhs); 159 } 160 161 template<class T1, class T2, class U1, class U2> 162 constexpr bool operator>=(const BASE_NS::pair<T1, T2>& lhs, const BASE_NS::pair<U1, U2>& rhs) 163 { 164 return !(lhs < rhs); 165 } 166 BASE_END_NAMESPACE() 167 168 #endif // //API_BASE_CONTAINERS_PAIR_H 169