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_array : false_type {}; 59 60 template <typename T> 61 struct is_array<T[]> : true_type {}; 62 63 template <typename T, decltype(sizeof(int)) kSize> 64 struct is_array<T[kSize]> : true_type {}; 65 66 template <typename T> 67 inline constexpr bool is_array_v = is_array<T>::value; 68 69 template <typename T> 70 struct is_const : false_type {}; 71 72 template <typename T> 73 struct is_const<const T> : true_type {}; 74 75 // NOT IMPLEMENTED: is_enum requires compiler builtins. 76 template <typename T> 77 struct is_enum : false_type {}; 78 79 template <typename T> 80 inline constexpr bool is_enum_v = is_enum<T>::value; 81 82 template <typename T> 83 struct remove_cv; // Forward declaration 84 85 namespace impl { 86 87 template <typename T> 88 struct is_floating_point : false_type {}; 89 90 template <> 91 struct is_floating_point<float> : true_type {}; 92 template <> 93 struct is_floating_point<double> : true_type {}; 94 template <> 95 struct is_floating_point<long double> : true_type {}; 96 97 } // namespace impl 98 99 template <typename T> 100 struct is_floating_point 101 : impl::is_floating_point<typename remove_cv<T>::type> {}; 102 103 template <typename T> 104 inline constexpr bool is_floating_point_v = is_floating_point<T>::value; 105 106 namespace impl { 107 108 template <typename T> 109 struct is_integral : false_type {}; 110 111 template <> 112 struct is_integral<bool> : true_type {}; 113 template <> 114 struct is_integral<char> : true_type {}; 115 template <> 116 struct is_integral<char16_t> : true_type {}; 117 template <> 118 struct is_integral<char32_t> : true_type {}; 119 template <> 120 struct is_integral<wchar_t> : true_type {}; 121 122 template <> 123 struct is_integral<short> : true_type {}; 124 template <> 125 struct is_integral<unsigned short> : true_type {}; 126 template <> 127 struct is_integral<int> : true_type {}; 128 template <> 129 struct is_integral<unsigned int> : true_type {}; 130 template <> 131 struct is_integral<long> : true_type {}; 132 template <> 133 struct is_integral<unsigned long> : true_type {}; 134 template <> 135 struct is_integral<long long> : true_type {}; 136 template <> 137 struct is_integral<unsigned long long> : true_type {}; 138 139 } // namespace impl 140 141 template <typename T> 142 struct is_integral : impl::is_integral<typename remove_cv<T>::type> {}; 143 144 template <typename T> 145 inline constexpr bool is_integral_v = is_integral<T>::value; 146 147 template <typename T> 148 struct is_arithmetic 149 : bool_constant<is_integral_v<T> || is_floating_point_v<T>> {}; 150 151 template <typename T> 152 inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value; 153 154 #define __cpp_lib_is_null_pointer 201309L 155 156 template <typename T> 157 struct is_null_pointer : false_type {}; 158 159 template <> 160 struct is_null_pointer<decltype(nullptr)> : true_type {}; 161 162 template <typename T> 163 inline constexpr bool is_null_pointer_v = is_null_pointer<T>::value; 164 165 template <typename T> 166 struct is_pointer : false_type {}; 167 168 template <typename T> 169 struct is_pointer<T*> : true_type {}; 170 171 template <typename T> 172 inline constexpr bool is_pointer_v = is_pointer<T>::value; 173 174 template <typename T, typename U> 175 struct is_same : false_type {}; 176 177 template <typename T> 178 struct is_same<T, T> : true_type {}; 179 180 template <typename T, typename U> 181 inline constexpr bool is_same_v = is_same<T, U>::value; 182 183 namespace impl { 184 185 template <typename T, bool = is_arithmetic<T>::value> 186 struct is_signed : integral_constant<bool, T(-1) < T(0)> {}; 187 188 template <typename T> 189 struct is_signed<T, false> : false_type {}; 190 191 } // namespace impl 192 193 template <typename T> 194 struct is_signed : impl::is_signed<T>::type {}; 195 196 template <typename T> 197 inline constexpr bool is_signed_v = is_signed<T>::value; 198 199 template <typename T> 200 struct is_unsigned : bool_constant<!is_signed_v<T>> {}; 201 202 template <typename T> 203 inline constexpr bool is_unsigned_v = is_unsigned<T>::value; 204 205 template <typename T> 206 struct is_void : is_same<void, typename remove_cv<T>::type> {}; 207 208 template <typename T> 209 inline constexpr bool is_void_v = is_void<T>::value; 210 211 template <bool kBool, typename TrueType, typename FalseType> 212 struct conditional { 213 using type = TrueType; 214 }; 215 216 template <typename TrueType, typename FalseType> 217 struct conditional<false, TrueType, FalseType> { 218 using type = FalseType; 219 }; 220 221 template <bool kBool, typename TrueType, typename FalseType> 222 using conditional_t = typename conditional<kBool, TrueType, FalseType>::type; 223 224 #define __cpp_lib_logical_traits 201510L 225 226 template <typename...> 227 struct conjunction; 228 229 template <> 230 struct conjunction<> : true_type {}; 231 232 template <typename T> 233 struct conjunction<T> : T {}; 234 235 template <typename First, typename... Others> 236 struct conjunction<First, Others...> 237 : conditional_t<bool(First::value), conjunction<Others...>, First> {}; 238 239 template <typename... Types> 240 inline constexpr bool conjunction_v = conjunction<Types...>::value; 241 242 template <typename...> 243 struct disjunction; 244 245 template <> 246 struct disjunction<> : false_type {}; 247 248 template <typename T> 249 struct disjunction<T> : T {}; 250 251 template <typename First, typename... Others> 252 struct disjunction<First, Others...> 253 : conditional_t<bool(First::value), First, disjunction<Others...>> {}; 254 255 template <typename... Types> 256 inline constexpr bool disjunction_v = disjunction<Types...>::value; 257 258 template <typename T> 259 struct negation : bool_constant<!bool(T::value)> {}; 260 261 template <typename T> 262 inline constexpr bool negation_v = negation<T>::value; 263 264 template <bool kEnable, typename T = void> 265 struct enable_if { 266 using type = T; 267 }; 268 269 template <typename T> 270 struct enable_if<false, T> {}; 271 272 template <bool kEnable, typename T = void> 273 using enable_if_t = typename enable_if<kEnable, T>::type; 274 275 template <typename T> 276 struct remove_const { 277 using type = T; 278 }; 279 280 template <typename T> 281 struct remove_const<const T> { 282 using type = T; 283 }; 284 285 template <typename T> 286 using remove_const_t = typename remove_const<T>::type; 287 288 template <typename T> 289 struct remove_volatile { 290 using type = T; 291 }; 292 293 template <typename T> 294 struct remove_volatile<volatile T> { 295 using type = T; 296 }; 297 298 template <typename T> 299 using remove_volatile_t = typename remove_volatile<T>::type; 300 301 template <typename T> 302 struct remove_cv { 303 using type = remove_volatile_t<remove_const_t<T>>; 304 }; 305 306 template <typename T> 307 using remove_cv_t = typename remove_cv<T>::type; 308 309 template <typename T> 310 struct remove_extent { 311 using type = T; 312 }; 313 314 template <typename T> 315 struct remove_extent<T[]> { 316 using type = T; 317 }; 318 319 template <typename T, decltype(sizeof(0)) kSize> 320 struct remove_extent<T[kSize]> { 321 using type = T; 322 }; 323 324 template <typename T> 325 using remove_extent_t = typename remove_extent<T>::type; 326 327 template <typename T> 328 struct remove_pointer { 329 using type = T; 330 }; 331 332 template <typename T> 333 struct remove_pointer<T*> { 334 using type = T; 335 }; 336 337 template <typename T> 338 struct remove_pointer<T* const> { 339 using type = T; 340 }; 341 342 template <typename T> 343 struct remove_pointer<T* volatile> { 344 using type = T; 345 }; 346 347 template <typename T> 348 struct remove_pointer<T* const volatile> { 349 using type = T; 350 }; 351 352 template <typename T> 353 using remove_pointer_t = typename remove_pointer<T>::type; 354 355 template <typename T> 356 struct remove_reference { 357 using type = T; 358 }; 359 360 template <typename T> 361 struct remove_reference<T&> { 362 using type = T; 363 }; 364 365 template <typename T> 366 struct remove_reference<T&&> { 367 using type = T; 368 }; 369 370 template <typename T> 371 using remove_reference_t = typename remove_reference<T>::type; 372 373 // NOT IMPLEMENTED: This implementation is INCOMPLETE, as it does not cover 374 // function types. 375 template <typename T> 376 struct decay { 377 private: 378 using U = remove_reference_t<T>; 379 380 public: 381 using type = 382 conditional_t<is_array<U>::value, remove_extent_t<U>*, remove_cv_t<U>>; 383 }; 384 385 template <typename T> 386 using decay_t = typename decay<T>::type; 387 388 #define __cpp_lib_type_identity 201806 389 390 template <class T> 391 struct type_identity { 392 using type = T; 393 }; 394 395 template <typename T> 396 using type_identity_t = typename type_identity<T>::type; 397 398 #define __cpp_lib_void_t void_t 201411L 399 400 template <typename...> 401 using void_t = void; 402 403 namespace impl { 404 405 template <typename T> 406 type_identity<T&> AddLValueReference(int); 407 408 template <typename T> 409 type_identity<T> AddLValueReference(...); 410 411 template <typename T> 412 type_identity<T&&> AddRValueReference(int); 413 414 template <typename T> 415 type_identity<T> AddRValueReference(...); 416 417 } // namespace impl 418 419 template <class T> 420 struct add_lvalue_reference : decltype(impl::AddLValueReference<T>(0)) {}; 421 422 template <typename T> 423 using add_lvalue_reference_t = typename add_lvalue_reference<T>::type; 424 425 template <class T> 426 struct add_rvalue_reference : decltype(impl::AddRValueReference<T>(0)) {}; 427 428 template <typename T> 429 using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; 430 431 template <typename T> 432 add_rvalue_reference_t<T> declval() noexcept; 433 434 namespace impl { 435 436 template <class T> 437 struct add_const { 438 typedef const T type; 439 }; 440 441 } // namespace impl 442 443 template <class T> 444 using add_const_t = typename impl::add_const<T>::type; 445 446 template <typename T> 447 struct make_signed; 448 449 template <typename T> 450 struct make_unsigned; 451 452 #define _PW_MAKE_SIGNED_SPECIALIZATION(base, signed_type, unsigned_type) \ 453 template <> \ 454 struct make_signed<base> { \ 455 using type = signed_type; \ 456 }; \ 457 template <> \ 458 struct make_unsigned<base> { \ 459 using type = unsigned_type; \ 460 } 461 462 _PW_MAKE_SIGNED_SPECIALIZATION(char, signed char, unsigned char); 463 _PW_MAKE_SIGNED_SPECIALIZATION(signed char, signed char, unsigned char); 464 _PW_MAKE_SIGNED_SPECIALIZATION(unsigned char, signed char, unsigned char); 465 466 _PW_MAKE_SIGNED_SPECIALIZATION(short, signed short, unsigned short); 467 _PW_MAKE_SIGNED_SPECIALIZATION(unsigned short, signed short, unsigned short); 468 469 _PW_MAKE_SIGNED_SPECIALIZATION(int, signed int, unsigned int); 470 _PW_MAKE_SIGNED_SPECIALIZATION(unsigned int, signed int, unsigned int); 471 472 _PW_MAKE_SIGNED_SPECIALIZATION(long, signed long, unsigned long); 473 _PW_MAKE_SIGNED_SPECIALIZATION(unsigned long, signed long, unsigned long); 474 475 _PW_MAKE_SIGNED_SPECIALIZATION(long long, signed short, unsigned short); 476 _PW_MAKE_SIGNED_SPECIALIZATION(unsigned long long, 477 signed short, 478 unsigned short); 479 480 // Skip specializations for char8_t, etc. 481 482 template <typename T> 483 using make_signed_t = typename make_signed<T>::type; 484 485 template <typename T> 486 using make_unsigned_t = typename make_unsigned<T>::type; 487 488 namespace impl { 489 490 template <typename> 491 using templated_true = true_type; 492 493 template <typename T> 494 auto returnable(int) -> templated_true<T()>; 495 496 template <typename> 497 auto returnable(...) -> false_type; 498 499 template <typename From, typename To> 500 auto convertible(int) 501 -> templated_true<decltype(declval<void (&)(To)>()(declval<From>()))>; 502 503 template <typename, typename> 504 auto convertible(...) -> false_type; 505 506 } // namespace impl 507 508 template <typename From, typename To> 509 struct is_convertible 510 : bool_constant<(decltype(impl::returnable<To>(0))() && 511 decltype(impl::convertible<From, To>(0))()) || 512 (is_void_v<From> && is_void_v<To>)> {}; 513 514 template <typename T, typename U> 515 inline constexpr bool is_convertible_v = is_convertible<T, U>::value; 516 517 // NOT IMPLEMENTED: Stubs are provided for these traits classes, but they do not 518 // return useful values. Many of these would require compiler builtins. 519 template <typename T> 520 struct is_function : false_type {}; 521 template <typename T> 522 struct is_trivially_copyable : true_type {}; 523 template <typename T> 524 struct is_polymorphic : false_type {}; 525 template <typename T, typename U> 526 struct is_base_of : false_type {}; 527 template <typename T> 528 struct extent : integral_constant<decltype(sizeof(int)), 1> {}; 529 template <typename T> 530 inline constexpr bool extent_v = extent<T>::value; 531 template <typename T> 532 struct underlying_type { 533 using type = T; 534 }; 535 template <typename T> 536 using underlying_type_t = typename underlying_type<T>::type; 537 template <typename T> 538 inline constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value; 539 540 _PW_POLYFILL_END_NAMESPACE_STD 541