1 /* 2 * Copyright (c) 2024 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_TYPE_TRAITS_H 17 #define API_BASE_CONTAINERS_TYPE_TRAITS_H 18 19 #include <cstddef> 20 21 #include <base/namespace.h> 22 23 BASE_BEGIN_NAMESPACE() 24 template<class T, T v> 25 struct integral_constant { 26 static constexpr T value = v; 27 using value_type = T; 28 using type = integral_constant; value_typeintegral_constant29 constexpr operator value_type() const noexcept 30 { 31 return (value); 32 } operatorintegral_constant33 constexpr value_type operator()() const noexcept 34 { 35 return (value); 36 } 37 }; 38 39 using false_type = integral_constant<bool, false>; 40 using true_type = integral_constant<bool, true>; 41 42 template<bool B, class T = void> 43 struct enable_if {}; 44 template<class T> 45 struct enable_if<true, T> { 46 using type = T; 47 }; 48 template<bool B, class T = void> 49 using enable_if_t = typename enable_if<B, T>::type; 50 51 template<class T, class U> 52 struct is_same : false_type {}; 53 template<class T> 54 struct is_same<T, T> : true_type {}; 55 56 template<class T, class U> 57 constexpr auto is_same_v = is_same<T, U>::value; 58 59 template<class T> 60 struct remove_extent { 61 using type = T; 62 }; 63 template<class T> 64 struct remove_extent<T[]> { 65 using type = T; 66 }; 67 template<class T, size_t N> 68 struct remove_extent<T[N]> { 69 using type = T; 70 }; 71 template<class T> 72 using remove_extent_t = typename remove_extent<T>::type; 73 74 template<class T, unsigned N = 0> 75 struct extent : integral_constant<size_t, 0> {}; 76 77 template<class T> 78 struct extent<T[], 0> : integral_constant<size_t, 0> {}; 79 80 template<class T, unsigned N> 81 struct extent<T[], N> : extent<T, N - 1> {}; 82 83 template<class T, size_t I> 84 struct extent<T[I], 0> : integral_constant<size_t, I> {}; 85 86 template<class T, size_t I, unsigned N> 87 struct extent<T[I], N> : extent<T, N - 1> {}; 88 89 template<class T, unsigned N = 0> 90 inline constexpr size_t extent_v = extent<T, N>::value; 91 92 template<class T> 93 struct remove_const { 94 using type = T; 95 }; 96 template<class T> 97 struct remove_const<const T> { 98 using type = T; 99 }; 100 template<class T> 101 using remove_const_t = typename remove_const<T>::type; 102 103 template<class T> 104 struct is_const : false_type {}; 105 template<class T> 106 struct is_const<const T> : true_type {}; 107 template<class T> 108 constexpr auto is_const_v = is_const<T>::value; 109 110 template<class T> 111 struct is_array : false_type {}; 112 template<class T> 113 struct is_array<T[]> : true_type {}; 114 template<class T, size_t N> 115 struct is_array<T[N]> : true_type {}; 116 template<class T> 117 constexpr bool is_array_v = is_array<T>::value; 118 template<class T> 119 using is_array_t = typename is_array<T>::type; 120 121 template<class T> 122 struct is_pointer : false_type {}; 123 template<class T> 124 struct is_pointer<T*> : true_type {}; 125 template<class T> 126 constexpr auto is_pointer_v = is_pointer<T>::value; 127 128 template<class T> 129 struct is_reference : false_type {}; 130 template<class T> 131 struct is_reference<T&> : true_type {}; 132 template<class T> 133 struct is_reference<T&&> : true_type {}; 134 template<class T> 135 constexpr bool is_reference_v = is_reference<T>::value; 136 137 template<class T> 138 struct is_lvalue_reference : false_type {}; 139 template<class T> 140 struct is_lvalue_reference<T&> : true_type {}; 141 template<class T> 142 constexpr bool is_lvalue_reference_v = is_lvalue_reference<T>::value; 143 144 template<class T> 145 struct is_rvalue_reference : false_type {}; 146 template<class T> 147 struct is_rvalue_reference<T&&> : true_type {}; 148 template<class T> 149 constexpr bool is_rvalue_reference_v = is_rvalue_reference<T>::value; 150 151 template<class... _Types> 152 using void_t = void; 153 154 template<class T, class = void> 155 struct add_lvalue_reference { 156 using type = T; 157 }; 158 template<class T, class = void> 159 struct add_rvalue_reference { 160 using type = T; 161 }; 162 template<class T> 163 struct add_lvalue_reference<T, void_t<T&>> { 164 using type = T&; 165 }; 166 template<class T> 167 struct add_rvalue_reference<T, void_t<T&>> { 168 using type = T&&; 169 }; 170 template<class T> 171 using add_lvalue_reference_t = typename add_lvalue_reference<T>::type; 172 template<class T> 173 using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; 174 175 template<class T> 176 struct remove_pointer { 177 using type = T; 178 }; 179 template<class T> 180 struct remove_pointer<T*> { 181 using type = T; 182 }; 183 template<class T> 184 struct remove_pointer<T* const> { 185 using type = T; 186 }; 187 template<class T> 188 using remove_pointer_t = typename remove_pointer<T>::type; 189 190 template<class T> 191 add_rvalue_reference_t<T> declval() noexcept; 192 193 template<class T> 194 struct remove_reference { 195 using type = T; 196 }; 197 198 template<class T> 199 struct remove_reference<T&> { 200 using type = T; 201 }; 202 203 template<class T> 204 struct remove_reference<T&&> { 205 using type = T; 206 }; 207 208 template<class T> 209 using remove_reference_t = typename remove_reference<T>::type; 210 211 template<class T> 212 constexpr remove_reference_t<T>&& move(T&& obj) noexcept 213 { 214 static_assert(!is_const<typename remove_reference<T>::type>::value, "move of const object is invalid."); 215 return (static_cast<remove_reference_t<T>&&>(obj)); 216 } 217 218 template<class T> 219 constexpr T&& forward(remove_reference_t<T>& obj) noexcept 220 { 221 return (static_cast<T&&>(obj)); 222 } 223 224 template<class T> 225 constexpr T&& forward(remove_reference_t<T>&& obj) noexcept 226 { 227 static_assert(!is_lvalue_reference_v<T>, "bad forward call"); 228 return (static_cast<T&&>(obj)); 229 } 230 231 using nullptr_t = decltype(nullptr); 232 233 template<class T, class U = T> 234 constexpr T exchange(T& obj, U&& newValue) 235 { 236 T old_value = move(obj); 237 obj = forward<U>(newValue); 238 return old_value; 239 } 240 241 template<typename T> 242 struct type_identity { 243 using type = T; 244 }; 245 246 template<class T> 247 using type_identity_t = typename type_identity<T>::type; 248 249 template<bool Condition, class TrueType, class FalseType> 250 struct conditional { 251 using type = TrueType; 252 }; 253 template<class TrueType, class FalseType> 254 struct conditional<false, TrueType, FalseType> { 255 using type = FalseType; 256 }; 257 template<bool Condition, class TrueType, class FalseType> 258 using conditional_t = typename conditional<Condition, TrueType, FalseType>::type; 259 260 template<class T> 261 struct is_void : is_same<void, remove_const_t<T>> {}; 262 template<typename T> 263 inline constexpr bool is_void_v = is_void<T>::value; 264 265 template<typename T> 266 struct is_floating_point 267 : integral_constant<bool, is_same_v<float, remove_const_t<T>> || is_same_v<double, remove_const_t<T>> || 268 is_same_v<long double, remove_const_t<T>>> {}; 269 template<typename T> 270 inline constexpr bool is_floating_point_v = is_floating_point<T>::value; 271 272 namespace detail { 273 template<typename T> 274 struct is_integral : false_type {}; 275 276 template<> 277 struct is_integral<bool> : true_type {}; 278 279 template<> 280 struct is_integral<signed char> : true_type {}; 281 282 template<> 283 struct is_integral<short> : true_type {}; 284 285 template<> 286 struct is_integral<int> : true_type {}; 287 288 template<> 289 struct is_integral<long> : true_type {}; 290 291 template<> 292 struct is_integral<long long> : true_type {}; 293 294 template<> 295 struct is_integral<unsigned char> : true_type {}; 296 297 template<> 298 struct is_integral<unsigned short> : true_type {}; 299 300 template<> 301 struct is_integral<unsigned int> : true_type {}; 302 303 template<> 304 struct is_integral<unsigned long> : true_type {}; 305 306 template<> 307 struct is_integral<unsigned long long> : true_type {}; 308 } // namespace detail 309 310 template<typename T> 311 struct is_integral : detail::is_integral<remove_const_t<T>>::type {}; 312 313 template<class T> 314 inline constexpr bool is_integral_v = is_integral<T>::value; 315 316 template<class T> 317 struct is_arithmetic : integral_constant<bool, is_integral_v<T> || is_floating_point_v<T>> {}; 318 319 template<class T> 320 inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value; 321 322 template<typename T, bool = is_arithmetic_v<T>> 323 struct is_unsigned : integral_constant<bool, T(0) < T(-1)> {}; 324 325 template<typename T> 326 struct is_unsigned<T, false> : false_type {}; 327 328 template<typename T> 329 inline constexpr bool is_unsigned_v = is_unsigned<T>::value; 330 331 template<typename T, bool = is_arithmetic_v<T>> 332 struct is_signed : integral_constant<bool, T(-1) < T(0)> {}; 333 334 template<typename T> 335 struct is_signed<T, false> : false_type {}; 336 337 template<typename T> 338 inline constexpr bool is_signed_v = is_signed<T>::value; 339 340 namespace detail { 341 template<typename T> 342 auto is_returnable(int) -> decltype(void(static_cast<T (*)()>(nullptr)), true_type {}); 343 344 template<typename> 345 auto is_returnable(...) -> false_type; 346 347 template<typename T> 348 inline constexpr bool is_returnable_v = decltype(is_returnable<T>(0))::value; 349 350 template<typename From, typename To> 351 auto is_implicitly_convertible(int) -> decltype(void(declval<void (&)(To)>()(declval<From>())), true_type {}); 352 353 template<typename, typename> 354 auto is_implicitly_convertible(...) -> false_type; 355 356 template<typename From, typename To> 357 inline constexpr bool is_implicitly_convertible_v = decltype(is_implicitly_convertible<From, To>(0))::value; 358 } // namespace detail 359 360 template<typename From, typename To> 361 struct is_convertible 362 : integral_constant<bool, (is_void_v<From> && is_void_v<To>) || 363 (detail::is_returnable_v<To> && detail::is_implicitly_convertible_v<From, To>)> {}; 364 template<typename From, typename To> 365 constexpr bool is_convertible_v = is_convertible<From, To>::value; 366 367 // return underlying type, works atleast for enums. 368 template<typename _Ty> 369 struct underlying_type { 370 using type = __underlying_type(_Ty); 371 }; 372 template<typename _Ty> 373 using underlying_type_t = typename underlying_type<_Ty>::type; 374 375 template<typename T, size_t N> 376 constexpr size_t countof(T (&)[N]) noexcept 377 { 378 return N; 379 } 380 BASE_END_NAMESPACE() 381 382 #endif // API_BASE_TYPE_TRAITS_H 383