1 // Copyright 2020 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://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, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include "pw_polyfill/standard_library/namespace.h" 17 18 _PW_POLYFILL_BEGIN_NAMESPACE_STD 19 20 #define __cpp_lib_transformation_trait_aliases 201304L 21 #define __cpp_lib_type_trait_variable_templates 201510L 22 23 template <decltype(sizeof(0)) kLength, 24 decltype(sizeof(0)) kAlignment> // no default 25 struct aligned_storage { 26 struct type { 27 alignas(kAlignment) unsigned char __data[kLength]; 28 }; 29 }; 30 31 template <decltype(sizeof(0)) kLength, 32 decltype(sizeof(0)) kAlignment> // no default 33 using aligned_storage_t = typename aligned_storage<kLength, kAlignment>::type; 34 35 #define __cpp_lib_integral_constant_callable 201304L 36 37 template <typename T, T kValue> 38 struct integral_constant { 39 using value_type = T; 40 using type = integral_constant; 41 42 static constexpr T value = kValue; 43 value_typeintegral_constant44 constexpr operator value_type() const noexcept { return value; } 45 operatorintegral_constant46 constexpr value_type operator()() const noexcept { return value; } 47 }; 48 49 #define __cpp_lib_bool_constant 201505L 50 51 template <bool kValue> 52 using bool_constant = integral_constant<bool, kValue>; 53 54 using true_type = bool_constant<true>; 55 using false_type = bool_constant<false>; 56 57 template <typename T> 58 struct is_aggregate : bool_constant<__is_aggregate(T)> {}; 59 60 template <typename T> 61 static constexpr bool is_aggregate_v = is_aggregate<T>::value; 62 63 template <typename T> 64 struct is_array : false_type {}; 65 template <typename T> 66 struct is_array<T[]> : true_type {}; 67 template <typename T, decltype(sizeof(0)) kSize> 68 struct is_array<T[kSize]> : true_type {}; 69 template <typename T> 70 inline constexpr bool is_array_v = is_array<T>::value; 71 72 template <typename T> 73 struct is_const : false_type {}; 74 template <typename T> 75 struct is_const<const T> : true_type {}; 76 template <typename T> 77 inline constexpr bool is_const_v = is_const<T>::value; 78 79 template <typename T> 80 struct is_lvalue_reference : false_type {}; 81 template <typename T> 82 struct is_lvalue_reference<T&> : true_type {}; 83 template <typename T> 84 inline constexpr bool is_lvalue_reference_v = is_lvalue_reference<T>::value; 85 86 template <typename T> 87 struct is_rvalue_reference : false_type {}; 88 template <typename T> 89 struct is_rvalue_reference<T&&> : true_type {}; 90 template <typename T> 91 inline constexpr bool is_rvalue_reference_v = is_rvalue_reference<T>::value; 92 93 template <typename T> 94 struct remove_cv; // Forward declaration 95 96 namespace impl { 97 98 template <typename T> 99 struct is_floating_point : false_type {}; 100 101 template <> 102 struct is_floating_point<float> : true_type {}; 103 template <> 104 struct is_floating_point<double> : true_type {}; 105 template <> 106 struct is_floating_point<long double> : true_type {}; 107 108 } // namespace impl 109 110 template <typename T> 111 struct is_floating_point 112 : impl::is_floating_point<typename remove_cv<T>::type> {}; 113 114 template <typename T> 115 inline constexpr bool is_floating_point_v = is_floating_point<T>::value; 116 117 namespace impl { 118 119 template <typename T> 120 struct is_integral : false_type {}; 121 122 template <> 123 struct is_integral<bool> : true_type {}; 124 template <> 125 struct is_integral<char> : true_type {}; 126 template <> 127 struct is_integral<char16_t> : true_type {}; 128 template <> 129 struct is_integral<char32_t> : true_type {}; 130 template <> 131 struct is_integral<wchar_t> : true_type {}; 132 133 template <> 134 struct is_integral<short> : true_type {}; 135 template <> 136 struct is_integral<unsigned short> : true_type {}; 137 template <> 138 struct is_integral<int> : true_type {}; 139 template <> 140 struct is_integral<unsigned int> : true_type {}; 141 template <> 142 struct is_integral<long> : true_type {}; 143 template <> 144 struct is_integral<unsigned long> : true_type {}; 145 template <> 146 struct is_integral<long long> : true_type {}; 147 template <> 148 struct is_integral<unsigned long long> : true_type {}; 149 150 } // namespace impl 151 152 template <typename T> 153 struct is_integral : impl::is_integral<typename remove_cv<T>::type> {}; 154 155 template <typename T> 156 inline constexpr bool is_integral_v = is_integral<T>::value; 157 158 template <typename T> 159 struct is_arithmetic 160 : bool_constant<is_integral_v<T> || is_floating_point_v<T>> {}; 161 162 template <typename T> 163 inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value; 164 165 #define __cpp_lib_is_null_pointer 201309L 166 167 template <typename T> 168 struct is_null_pointer : false_type {}; 169 170 template <> 171 struct is_null_pointer<decltype(nullptr)> : true_type {}; 172 173 template <typename T> 174 inline constexpr bool is_null_pointer_v = is_null_pointer<T>::value; 175 176 template <typename T> 177 struct is_pointer : false_type {}; 178 179 template <typename T> 180 struct is_pointer<T*> : true_type {}; 181 182 template <typename T> 183 inline constexpr bool is_pointer_v = is_pointer<T>::value; 184 185 template <typename T, typename U> 186 struct is_same : false_type {}; 187 188 template <typename T> 189 struct is_same<T, T> : true_type {}; 190 191 template <typename T, typename U> 192 inline constexpr bool is_same_v = is_same<T, U>::value; 193 194 namespace impl { 195 196 template <typename T, bool = is_arithmetic<T>::value> 197 struct is_signed : integral_constant<bool, T(-1) < T(0)> {}; 198 199 template <typename T> 200 struct is_signed<T, false> : false_type {}; 201 202 } // namespace impl 203 204 template <typename T> 205 struct is_signed : impl::is_signed<T>::type {}; 206 207 template <typename T> 208 inline constexpr bool is_signed_v = is_signed<T>::value; 209 210 template <typename T> 211 struct is_unsigned : bool_constant<!is_signed_v<T>> {}; 212 213 template <typename T> 214 inline constexpr bool is_unsigned_v = is_unsigned<T>::value; 215 216 template <typename T> 217 struct is_void : is_same<void, typename remove_cv<T>::type> {}; 218 219 template <typename T> 220 inline constexpr bool is_void_v = is_void<T>::value; 221 222 template <bool kBool, typename TrueType, typename FalseType> 223 struct conditional { 224 using type = TrueType; 225 }; 226 227 template <typename TrueType, typename FalseType> 228 struct conditional<false, TrueType, FalseType> { 229 using type = FalseType; 230 }; 231 232 template <bool kBool, typename TrueType, typename FalseType> 233 using conditional_t = typename conditional<kBool, TrueType, FalseType>::type; 234 235 #define __cpp_lib_logical_traits 201510L 236 237 template <typename...> 238 struct conjunction; 239 240 template <> 241 struct conjunction<> : true_type {}; 242 243 template <typename T> 244 struct conjunction<T> : T {}; 245 246 template <typename First, typename... Others> 247 struct conjunction<First, Others...> 248 : conditional_t<bool(First::value), conjunction<Others...>, First> {}; 249 250 template <typename... Types> 251 inline constexpr bool conjunction_v = conjunction<Types...>::value; 252 253 template <typename...> 254 struct disjunction; 255 256 template <> 257 struct disjunction<> : false_type {}; 258 259 template <typename T> 260 struct disjunction<T> : T {}; 261 262 template <typename First, typename... Others> 263 struct disjunction<First, Others...> 264 : conditional_t<bool(First::value), First, disjunction<Others...>> {}; 265 266 template <typename... Types> 267 inline constexpr bool disjunction_v = disjunction<Types...>::value; 268 269 template <typename T> 270 struct negation : bool_constant<!bool(T::value)> {}; 271 272 template <typename T> 273 inline constexpr bool negation_v = negation<T>::value; 274 275 template <bool kEnable, typename T = void> 276 struct enable_if { 277 using type = T; 278 }; 279 280 template <typename T> 281 struct enable_if<false, T> {}; 282 283 template <bool kEnable, typename T = void> 284 using enable_if_t = typename enable_if<kEnable, T>::type; 285 286 template <typename T> 287 struct remove_const { 288 using type = T; 289 }; 290 291 template <typename T> 292 struct remove_const<const T> { 293 using type = T; 294 }; 295 296 template <typename T> 297 using remove_const_t = typename remove_const<T>::type; 298 299 template <typename T> 300 struct remove_volatile { 301 using type = T; 302 }; 303 304 template <typename T> 305 struct remove_volatile<volatile T> { 306 using type = T; 307 }; 308 309 template <typename T> 310 using remove_volatile_t = typename remove_volatile<T>::type; 311 312 template <typename T> 313 struct remove_cv { 314 using type = remove_volatile_t<remove_const_t<T>>; 315 }; 316 317 template <typename T> 318 using remove_cv_t = typename remove_cv<T>::type; 319 320 template <typename T> 321 struct remove_extent { 322 using type = T; 323 }; 324 325 template <typename T> 326 struct remove_extent<T[]> { 327 using type = T; 328 }; 329 330 template <typename T, decltype(sizeof(0)) kSize> 331 struct remove_extent<T[kSize]> { 332 using type = T; 333 }; 334 335 template <typename T> 336 using remove_extent_t = typename remove_extent<T>::type; 337 338 template <typename T> 339 struct remove_pointer { 340 using type = T; 341 }; 342 343 template <typename T> 344 struct remove_pointer<T*> { 345 using type = T; 346 }; 347 348 template <typename T> 349 struct remove_pointer<T* const> { 350 using type = T; 351 }; 352 353 template <typename T> 354 struct remove_pointer<T* volatile> { 355 using type = T; 356 }; 357 358 template <typename T> 359 struct remove_pointer<T* const volatile> { 360 using type = T; 361 }; 362 363 template <typename T> 364 using remove_pointer_t = typename remove_pointer<T>::type; 365 366 template <typename T> 367 struct remove_reference { 368 using type = T; 369 }; 370 371 template <typename T> 372 struct remove_reference<T&> { 373 using type = T; 374 }; 375 376 template <typename T> 377 struct remove_reference<T&&> { 378 using type = T; 379 }; 380 381 template <typename T> 382 using remove_reference_t = typename remove_reference<T>::type; 383 384 // NOT IMPLEMENTED: This implementation is INCOMPLETE, as it does not cover 385 // function types. 386 template <typename T> 387 struct decay { 388 private: 389 using U = remove_reference_t<T>; 390 391 public: 392 using type = 393 conditional_t<is_array<U>::value, remove_extent_t<U>*, remove_cv_t<U>>; 394 }; 395 396 template <typename T> 397 using decay_t = typename decay<T>::type; 398 399 #define __cpp_lib_type_identity 201806 400 401 template <class T> 402 struct type_identity { 403 using type = T; 404 }; 405 406 template <typename T> 407 using type_identity_t = typename type_identity<T>::type; 408 409 #define __cpp_lib_void_t 201411L 410 411 template <typename...> 412 using void_t = void; 413 414 namespace impl { 415 416 template <typename T> 417 type_identity<T&> AddLValueReference(int); 418 419 template <typename T> 420 type_identity<T> AddLValueReference(...); 421 422 template <typename T> 423 type_identity<T&&> AddRValueReference(int); 424 425 template <typename T> 426 type_identity<T> AddRValueReference(...); 427 428 } // namespace impl 429 430 template <class T> 431 struct add_lvalue_reference : decltype(impl::AddLValueReference<T>(0)) {}; 432 433 template <typename T> 434 using add_lvalue_reference_t = typename add_lvalue_reference<T>::type; 435 436 template <class T> 437 struct add_rvalue_reference : decltype(impl::AddRValueReference<T>(0)) {}; 438 439 template <typename T> 440 using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; 441 442 template <typename T> 443 add_rvalue_reference_t<T> declval() noexcept; 444 445 namespace impl { 446 447 template <class T> 448 struct add_const { 449 typedef const T type; 450 }; 451 452 } // namespace impl 453 454 template <class T> 455 using add_const_t = typename impl::add_const<T>::type; 456 457 template <typename T> 458 struct make_signed; 459 460 template <typename T> 461 struct make_unsigned; 462 463 #define _PW_MAKE_SIGNED_SPECIALIZATION(base, signed_type, unsigned_type) \ 464 template <> \ 465 struct make_signed<base> { \ 466 using type = signed_type; \ 467 }; \ 468 template <> \ 469 struct make_unsigned<base> { \ 470 using type = unsigned_type; \ 471 } 472 473 _PW_MAKE_SIGNED_SPECIALIZATION(char, signed char, unsigned char); 474 _PW_MAKE_SIGNED_SPECIALIZATION(signed char, signed char, unsigned char); 475 _PW_MAKE_SIGNED_SPECIALIZATION(unsigned char, signed char, unsigned char); 476 477 _PW_MAKE_SIGNED_SPECIALIZATION(short, signed short, unsigned short); 478 _PW_MAKE_SIGNED_SPECIALIZATION(unsigned short, signed short, unsigned short); 479 480 _PW_MAKE_SIGNED_SPECIALIZATION(int, signed int, unsigned int); 481 _PW_MAKE_SIGNED_SPECIALIZATION(unsigned int, signed int, unsigned int); 482 483 _PW_MAKE_SIGNED_SPECIALIZATION(long, signed long, unsigned long); 484 _PW_MAKE_SIGNED_SPECIALIZATION(unsigned long, signed long, unsigned long); 485 486 _PW_MAKE_SIGNED_SPECIALIZATION(long long, signed short, unsigned short); 487 _PW_MAKE_SIGNED_SPECIALIZATION(unsigned long long, 488 signed short, 489 unsigned short); 490 491 // Skip specializations for char8_t, etc. 492 493 template <typename T> 494 using make_signed_t = typename make_signed<T>::type; 495 496 template <typename T> 497 using make_unsigned_t = typename make_unsigned<T>::type; 498 499 namespace impl { 500 501 template <typename> 502 using templated_true = true_type; 503 504 template <typename T> 505 auto returnable(int) -> templated_true<T()>; 506 507 template <typename> 508 auto returnable(...) -> false_type; 509 510 template <typename From, typename To> 511 auto convertible(int) 512 -> templated_true<decltype(declval<void (&)(To)>()(declval<From>()))>; 513 514 template <typename, typename> 515 auto convertible(...) -> false_type; 516 517 } // namespace impl 518 519 template <typename From, typename To> 520 struct is_convertible 521 : bool_constant<(decltype(impl::returnable<To>(0))() && 522 decltype(impl::convertible<From, To>(0))()) || 523 (is_void_v<From> && is_void_v<To>)> {}; 524 525 template <typename T, typename U> 526 inline constexpr bool is_convertible_v = is_convertible<T, U>::value; 527 528 template <typename T> 529 struct alignment_of : integral_constant<decltype(sizeof(0)), alignof(T)> {}; 530 template <typename T> 531 inline constexpr decltype(sizeof(0)) alignment_of_v = alignment_of<T>::value; 532 533 #define PW_STDLIB_UNIMPLEMENTED(name) \ 534 [[deprecated(#name " is NOT IMPLEMENTED in pw_minimal_cpp_stdlib!")]] 535 536 // NOT IMPLEMENTED: Stubs are provided for these traits classes, but they do not 537 // return useful values. Many of these would require compiler builtins. 538 #define PW_BOOLEAN_TRAIT_NOT_SUPPORTED(name) \ 539 template <typename T> \ 540 struct name : false_type {}; \ 541 template <typename T> \ 542 PW_STDLIB_UNIMPLEMENTED(name) \ 543 inline constexpr bool name##_v = name<T>::value 544 545 #define PW_BOOLEAN_TRAIT_NOT_SUPPORTED_2(name) \ 546 template <typename T, typename U> \ 547 struct name : false_type {}; \ 548 template <typename T, typename U> \ 549 PW_STDLIB_UNIMPLEMENTED(name) \ 550 inline constexpr bool name##_v = name<T, U>::value 551 552 #define PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(name) \ 553 template <typename T, typename... Args> \ 554 struct name : false_type {}; \ 555 template <typename T, typename... Args> \ 556 PW_STDLIB_UNIMPLEMENTED(name) \ 557 inline constexpr bool name##_v = name<T, Args...>::value 558 559 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_class); 560 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_enum); 561 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_function); 562 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_member_function_pointer); 563 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_member_object_pointer); 564 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_union); 565 566 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_compound); 567 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_fundamental); 568 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_member_pointer); 569 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_object); 570 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_reference); 571 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_scalar); 572 573 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_abstract); 574 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_empty); 575 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_final); 576 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_pod); 577 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_polymorphic); 578 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_standard_layout); 579 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_trivial); 580 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_trivially_copyable); 581 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_volatile); 582 583 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_constructible); 584 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_nothrow_constructible); 585 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_trivially_constructible); 586 587 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_default_constructible); 588 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_nothrow_default_constructible); 589 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_trivially_default_constructible); 590 591 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_copy_constructible); 592 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_nothrow_copy_constructible); 593 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_trivially_copy_constructible); 594 595 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_move_constructible); 596 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_nothrow_move_constructible); 597 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_trivially_move_constructible); 598 599 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_assignable); 600 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_nothrow_assignable); 601 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_trivially_assignable); 602 603 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_copy_assignable); 604 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_nothrow_copy_assignable); 605 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_trivially_copy_assignable); 606 607 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_move_assignable); 608 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_nothrow_move_assignable); 609 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS(is_trivially_move_assignable); 610 611 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_destructible); 612 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_nothrow_destructible); 613 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_trivially_destructible); 614 615 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(has_virtual_destructor); 616 617 template <typename T> 618 struct extent : integral_constant<decltype(sizeof(0)), 1> {}; 619 template <typename T> 620 PW_STDLIB_UNIMPLEMENTED(extent) 621 inline constexpr decltype(sizeof(0)) extent_v = extent<T>::value; 622 623 template <typename T> 624 struct rank : integral_constant<decltype(sizeof(0)), 1> {}; 625 template <typename T> 626 PW_STDLIB_UNIMPLEMENTED(rank) 627 inline constexpr decltype(sizeof(0)) rank_v = extent<T>::value; 628 629 PW_BOOLEAN_TRAIT_NOT_SUPPORTED_2(is_base_of); 630 631 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_invocable_r); 632 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_invocable); 633 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_nothrow_invocable_r); 634 PW_BOOLEAN_TRAIT_NOT_SUPPORTED(is_nothrow_invocable); 635 636 template <typename T> 637 struct invoke_result {}; 638 template <typename T> 639 using invoke_result_t = typename invoke_result<T>::type; 640 641 template <typename T> 642 struct underlying_type { 643 using type = T; 644 }; 645 template <typename T> 646 using underlying_type_t = typename underlying_type<T>::type; 647 648 #undef PW_BOOLEAN_TRAIT_NOT_SUPPORTED 649 #undef PW_BOOLEAN_TRAIT_NOT_SUPPORTED_2 650 #undef PW_BOOLEAN_TRAIT_NOT_SUPPORTED_VARARGS 651 #undef PW_STDLIB_UNIMPLEMENTED 652 653 _PW_POLYFILL_END_NAMESPACE_STD 654