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_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 Base, class Derived> 60 struct is_base_of : integral_constant<bool, __is_base_of(Base, Derived)> {}; 61 62 template<class Base, class Derived> 63 constexpr bool is_base_of_v = is_base_of<Base, Derived>::value; 64 65 template<class T> 66 struct remove_extent { 67 using type = T; 68 }; 69 template<class T> 70 struct remove_extent<T[]> { 71 using type = T; 72 }; 73 template<class T, size_t N> 74 struct remove_extent<T[N]> { 75 using type = T; 76 }; 77 template<class T> 78 using remove_extent_t = typename remove_extent<T>::type; 79 80 template<class T, unsigned N = 0> 81 struct extent : integral_constant<size_t, 0> {}; 82 83 template<class T> 84 struct extent<T[], 0> : integral_constant<size_t, 0> {}; 85 86 template<class T, unsigned N> 87 struct extent<T[], N> : extent<T, N - 1> {}; 88 89 template<class T, size_t I> 90 struct extent<T[I], 0> : integral_constant<size_t, I> {}; 91 92 template<class T, size_t I, unsigned N> 93 struct extent<T[I], N> : extent<T, N - 1> {}; 94 95 template<class T, unsigned N = 0> 96 inline constexpr size_t extent_v = extent<T, N>::value; 97 98 template<class T> 99 struct remove_const { 100 using type = T; 101 }; 102 template<class T> 103 struct remove_const<const T> { 104 using type = T; 105 }; 106 template<class T> 107 using remove_const_t = typename remove_const<T>::type; 108 109 template<class T> 110 struct is_const : false_type {}; 111 template<class T> 112 struct is_const<const T> : true_type {}; 113 template<class T> 114 constexpr auto is_const_v = is_const<T>::value; 115 116 template<class T> 117 struct is_array : false_type {}; 118 template<class T> 119 struct is_array<T[]> : true_type {}; 120 template<class T, size_t N> 121 struct is_array<T[N]> : true_type {}; 122 template<class T> 123 constexpr bool is_array_v = is_array<T>::value; 124 template<class T> 125 using is_array_t = typename is_array<T>::type; 126 127 template<class T> 128 struct is_pointer : false_type {}; 129 template<class T> 130 struct is_pointer<T*> : true_type {}; 131 template<class T> 132 constexpr auto is_pointer_v = is_pointer<T>::value; 133 134 template<class T> 135 struct is_reference : false_type {}; 136 template<class T> 137 struct is_reference<T&> : true_type {}; 138 template<class T> 139 struct is_reference<T&&> : true_type {}; 140 template<class T> 141 constexpr bool is_reference_v = is_reference<T>::value; 142 143 template<class T> 144 struct is_lvalue_reference : false_type {}; 145 template<class T> 146 struct is_lvalue_reference<T&> : true_type {}; 147 template<class T> 148 constexpr bool is_lvalue_reference_v = is_lvalue_reference<T>::value; 149 150 template<class T> 151 struct is_rvalue_reference : false_type {}; 152 template<class T> 153 struct is_rvalue_reference<T&&> : true_type {}; 154 template<class T> 155 constexpr bool is_rvalue_reference_v = is_rvalue_reference<T>::value; 156 157 template<class... _Types> 158 using void_t = void; 159 160 template<class T, class = void> 161 struct add_lvalue_reference { 162 using type = T; 163 }; 164 template<class T, class = void> 165 struct add_rvalue_reference { 166 using type = T; 167 }; 168 template<class T> 169 struct add_lvalue_reference<T, void_t<T&>> { 170 using type = T&; 171 }; 172 template<class T> 173 struct add_rvalue_reference<T, void_t<T&>> { 174 using type = T&&; 175 }; 176 template<class T> 177 using add_lvalue_reference_t = typename add_lvalue_reference<T>::type; 178 template<class T> 179 using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; 180 181 template<class T> 182 struct remove_pointer { 183 using type = T; 184 }; 185 template<class T> 186 struct remove_pointer<T*> { 187 using type = T; 188 }; 189 template<class T> 190 struct remove_pointer<T* const> { 191 using type = T; 192 }; 193 template<class T> 194 using remove_pointer_t = typename remove_pointer<T>::type; 195 196 template<class T> 197 add_rvalue_reference_t<T> declval() noexcept; 198 199 template<class T> 200 struct remove_reference { 201 using type = T; 202 }; 203 204 template<class T> 205 struct remove_reference<T&> { 206 using type = T; 207 }; 208 209 template<class T> 210 struct remove_reference<T&&> { 211 using type = T; 212 }; 213 214 template<class T> 215 using remove_reference_t = typename remove_reference<T>::type; 216 217 template<class T> 218 constexpr remove_reference_t<T>&& move(T&& obj) noexcept 219 { 220 static_assert(!is_const<typename remove_reference<T>::type>::value, "move of const object is invalid."); 221 return (static_cast<remove_reference_t<T>&&>(obj)); 222 } 223 224 template<class T> 225 constexpr T&& forward(remove_reference_t<T>& obj) noexcept 226 { 227 return (static_cast<T&&>(obj)); 228 } 229 230 template<class T> 231 constexpr T&& forward(remove_reference_t<T>&& obj) noexcept 232 { 233 static_assert(!is_lvalue_reference_v<T>, "bad forward call"); 234 return (static_cast<T&&>(obj)); 235 } 236 237 using nullptr_t = decltype(nullptr); 238 239 template<class T, class U = T> 240 constexpr T exchange(T& obj, U&& newValue) 241 { 242 T old_value = move(obj); 243 obj = forward<U>(newValue); 244 return old_value; 245 } 246 247 template<typename T> 248 struct type_identity { 249 using type = T; 250 }; 251 252 template<class T> 253 using type_identity_t = typename type_identity<T>::type; 254 255 template<bool Condition, class TrueType, class FalseType> 256 struct conditional { 257 using type = TrueType; 258 }; 259 template<class TrueType, class FalseType> 260 struct conditional<false, TrueType, FalseType> { 261 using type = FalseType; 262 }; 263 template<bool Condition, class TrueType, class FalseType> 264 using conditional_t = typename conditional<Condition, TrueType, FalseType>::type; 265 266 template<class T> 267 struct is_void : is_same<void, remove_const_t<T>> {}; 268 template<typename T> 269 inline constexpr bool is_void_v = is_void<T>::value; 270 271 template<typename T> 272 struct is_floating_point 273 : integral_constant<bool, is_same_v<float, remove_const_t<T>> || is_same_v<double, remove_const_t<T>> || 274 is_same_v<long double, remove_const_t<T>>> {}; 275 template<typename T> 276 inline constexpr bool is_floating_point_v = is_floating_point<T>::value; 277 278 namespace detail { 279 template<typename T> 280 struct is_integral : false_type {}; 281 282 template<> 283 struct is_integral<bool> : true_type {}; 284 285 template<> 286 struct is_integral<signed char> : true_type {}; 287 288 template<> 289 struct is_integral<short> : true_type {}; 290 291 template<> 292 struct is_integral<int> : true_type {}; 293 294 template<> 295 struct is_integral<long> : true_type {}; 296 297 template<> 298 struct is_integral<long long> : true_type {}; 299 300 template<> 301 struct is_integral<unsigned char> : true_type {}; 302 303 template<> 304 struct is_integral<unsigned short> : true_type {}; 305 306 template<> 307 struct is_integral<unsigned int> : true_type {}; 308 309 template<> 310 struct is_integral<unsigned long> : true_type {}; 311 312 template<> 313 struct is_integral<unsigned long long> : true_type {}; 314 } // namespace detail 315 316 template<typename T> 317 struct is_integral : detail::is_integral<remove_const_t<T>>::type {}; 318 319 template<class T> 320 inline constexpr bool is_integral_v = is_integral<T>::value; 321 322 template<class T> 323 struct is_arithmetic : integral_constant<bool, is_integral_v<T> || is_floating_point_v<T>> {}; 324 325 template<class T> 326 inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value; 327 328 template<typename T, bool = is_arithmetic_v<T>> 329 struct is_unsigned : integral_constant<bool, T(0) < T(-1)> {}; 330 331 template<typename T> 332 struct is_unsigned<T, false> : false_type {}; 333 334 template<typename T> 335 inline constexpr bool is_unsigned_v = is_unsigned<T>::value; 336 337 template<typename T, bool = is_arithmetic_v<T>> 338 struct is_signed : integral_constant<bool, T(-1) < T(0)> {}; 339 340 template<typename T> 341 struct is_signed<T, false> : false_type {}; 342 343 template<typename T> 344 inline constexpr bool is_signed_v = is_signed<T>::value; 345 346 template<class T, class... Args> 347 struct is_constructible : integral_constant<bool, __is_constructible(T, Args...)> {}; 348 349 template<class T, class... Args> 350 constexpr bool is_constructible_v = is_constructible<T, Args...>::value; 351 352 template<class T, class... Args> 353 struct is_trivially_constructible : integral_constant<bool, __is_trivially_constructible(T, Args...)> {}; 354 355 template<class T, class... Args> 356 constexpr bool is_trivially_constructible_v = is_trivially_constructible<T, Args...>::value; 357 358 template<class T, class... Args> 359 struct is_nothrow_constructible : integral_constant<bool, __is_nothrow_constructible(T, Args...)> {}; 360 361 template<class T, class... Args> 362 constexpr bool is_nothrow_constructible_v = is_nothrow_constructible<T, Args...>::value; 363 364 template<class T> 365 struct is_default_constructible : is_constructible<T> {}; 366 367 template<class T> 368 inline constexpr bool is_default_constructible_v = is_default_constructible<T>::value; 369 370 template<class T> 371 struct is_trivially_default_constructible : is_trivially_constructible<T> {}; 372 373 template<class T> 374 inline constexpr bool is_trivially_default_constructible_v = is_trivially_default_constructible<T>::value; 375 376 template<class T> 377 struct is_nothrow_default_constructible : is_nothrow_constructible<T> {}; 378 379 template<class T> 380 inline constexpr bool is_nothrow_default_constructible_v = is_nothrow_default_constructible<T>::value; 381 382 template<class T> 383 struct is_copy_constructible : is_constructible<T, add_lvalue_reference_t<const T>> {}; 384 385 template<class T> 386 inline constexpr bool is_copy_constructible_v = is_copy_constructible<T>::value; 387 388 template<class T> 389 struct is_nothrow_copy_constructible : is_nothrow_constructible<T, add_lvalue_reference_t<const T>> {}; 390 391 template<class T> 392 constexpr bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible<T>::value; 393 394 template<class To, class From> 395 struct is_assignable : integral_constant<bool, __is_assignable(To, From)> {}; 396 397 template<class To, class From> 398 constexpr bool is_assignable_v = is_assignable<To, From>::value; 399 400 template<class To, class From> 401 struct is_trivially_assignable : integral_constant<bool, __is_trivially_assignable(To, From)> {}; 402 403 template<class To, class From> 404 constexpr bool is_trivially_assignable_v = is_trivially_assignable<To, From>::value; 405 406 template<class To, class From> 407 struct is_nothrow_assignable : integral_constant<bool, __is_nothrow_assignable(To, From)> {}; 408 409 template<class To, class From> 410 constexpr bool is_nothrow_assignable_v = is_nothrow_assignable<To, From>::value; 411 412 template<class T> 413 struct is_copy_assignable : is_assignable<add_lvalue_reference_t<T>, add_lvalue_reference_t<const T>> {}; 414 415 template<class T> 416 constexpr bool is_copy_assignable_v = is_copy_assignable<T>::value; 417 418 template<class T> 419 struct is_trivially_copy_assignable 420 : is_trivially_assignable<add_lvalue_reference_t<T>, add_lvalue_reference_t<const T>> {}; 421 422 template<class T> 423 constexpr bool is_trivially_copy_assignable_v = is_trivially_copy_assignable<T>::value; 424 425 template<class T> 426 struct is_nothrow_copy_assignable : is_nothrow_assignable<add_lvalue_reference_t<T>, add_lvalue_reference_t<const T>> { 427 }; 428 429 template<class T> 430 constexpr bool is_nothrow_copy_assignable_v = is_nothrow_copy_assignable<T>::value; 431 432 template<class T> 433 struct is_move_assignable : is_assignable<add_lvalue_reference_t<T>, T> {}; 434 435 template<class T> 436 constexpr bool is_move_assignable_v = is_move_assignable<T>::value; 437 438 template<class T> 439 struct is_trivially_move_assignable : is_trivially_assignable<add_lvalue_reference_t<T>, T> {}; 440 441 template<class T> 442 constexpr bool is_trivially_move_assignable_v = is_trivially_move_assignable<T>::value; 443 444 template<class T> 445 struct is_nothrow_move_assignable : is_nothrow_assignable<add_lvalue_reference_t<T>, T> {}; 446 447 template<class T> 448 constexpr bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<T>::value; 449 450 namespace detail { 451 template<typename T> 452 auto is_returnable(int) -> decltype(void(static_cast<T (*)()>(nullptr)), true_type {}); 453 454 template<typename> 455 auto is_returnable(...) -> false_type; 456 457 template<typename T> 458 inline constexpr bool is_returnable_v = decltype(is_returnable<T>(0))::value; 459 460 template<typename From, typename To> 461 auto is_implicitly_convertible(int) -> decltype(void(declval<void (&)(To)>()(declval<From>())), true_type {}); 462 463 template<typename, typename> 464 auto is_implicitly_convertible(...) -> false_type; 465 466 template<typename From, typename To> 467 inline constexpr bool is_implicitly_convertible_v = decltype(is_implicitly_convertible<From, To>(0))::value; 468 } // namespace detail 469 470 template<typename From, typename To> 471 struct is_convertible 472 : integral_constant<bool, (is_void_v<From> && is_void_v<To>) || 473 (detail::is_returnable_v<To> && detail::is_implicitly_convertible_v<From, To>)> {}; 474 template<typename From, typename To> 475 constexpr bool is_convertible_v = is_convertible<From, To>::value; 476 477 // return underlying type, works atleast for enums. 478 template<typename _Ty> 479 struct underlying_type { 480 using type = __underlying_type(_Ty); 481 }; 482 template<typename _Ty> 483 using underlying_type_t = typename underlying_type<_Ty>::type; 484 485 template<typename T, size_t N> 486 constexpr size_t countof(T (&)[N]) noexcept 487 { 488 return N; 489 } 490 BASE_END_NAMESPACE() 491 492 #endif // API_BASE_TYPE_TRAITS_H 493