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 #define __cpp_lib_logical_traits 201510L 23 24 template <decltype(sizeof(0)) kLength, 25 decltype(sizeof(0)) kAlignment> // no default 26 struct aligned_storage { 27 struct type { 28 alignas(kAlignment) unsigned char __data[kLength]; 29 }; 30 }; 31 32 template <decltype(sizeof(0)) kLength, 33 decltype(sizeof(0)) kAlignment> // no default 34 using aligned_storage_t = typename aligned_storage<kLength, kAlignment>::type; 35 36 #define __cpp_lib_integral_constant_callable 201304L 37 38 template <typename T, T kValue> 39 struct integral_constant { 40 using value_type = T; 41 using type = integral_constant; 42 43 static constexpr T value = kValue; 44 value_typeintegral_constant45 constexpr operator value_type() const noexcept { return value; } 46 operatorintegral_constant47 constexpr value_type operator()() const noexcept { return value; } 48 }; 49 50 #define __cpp_lib_bool_constant 201505L 51 52 template <bool kValue> 53 using bool_constant = integral_constant<bool, kValue>; 54 55 using true_type = bool_constant<true>; 56 using false_type = bool_constant<false>; 57 58 template <typename T> 59 struct is_array : false_type {}; 60 61 template <typename T> 62 struct is_array<T[]> : true_type {}; 63 64 template <typename T, decltype(sizeof(int)) kSize> 65 struct is_array<T[kSize]> : true_type {}; 66 67 template <typename T> 68 inline constexpr bool is_array_v = is_array<T>::value; 69 70 template <typename T> 71 struct is_const : false_type {}; 72 73 template <typename T> 74 struct is_const<const T> : true_type {}; 75 76 // NOT IMPLEMENTED: is_enum requires compiler builtins. 77 template <typename T> 78 struct is_enum : false_type {}; 79 80 template <typename T> 81 inline constexpr bool is_enum_v = is_enum<T>::value; 82 83 template <typename T> 84 struct remove_cv; // Forward declaration 85 86 namespace impl { 87 88 template <typename T> 89 struct is_floating_point : false_type {}; 90 91 template <> 92 struct is_floating_point<float> : true_type {}; 93 template <> 94 struct is_floating_point<double> : true_type {}; 95 template <> 96 struct is_floating_point<long double> : true_type {}; 97 98 } // namespace impl 99 100 template <typename T> 101 struct is_floating_point 102 : impl::is_floating_point<typename remove_cv<T>::type> {}; 103 104 template <typename T> 105 inline constexpr bool is_floating_point_v = is_floating_point<T>::value; 106 107 namespace impl { 108 109 template <typename T> 110 struct is_integral : false_type {}; 111 112 template <> 113 struct is_integral<bool> : true_type {}; 114 template <> 115 struct is_integral<char> : true_type {}; 116 template <> 117 struct is_integral<char16_t> : true_type {}; 118 template <> 119 struct is_integral<char32_t> : true_type {}; 120 template <> 121 struct is_integral<wchar_t> : true_type {}; 122 123 template <> 124 struct is_integral<short> : true_type {}; 125 template <> 126 struct is_integral<unsigned short> : true_type {}; 127 template <> 128 struct is_integral<int> : true_type {}; 129 template <> 130 struct is_integral<unsigned int> : true_type {}; 131 template <> 132 struct is_integral<long> : true_type {}; 133 template <> 134 struct is_integral<unsigned long> : true_type {}; 135 template <> 136 struct is_integral<long long> : true_type {}; 137 template <> 138 struct is_integral<unsigned long long> : true_type {}; 139 140 } // namespace impl 141 142 template <typename T> 143 struct is_integral : impl::is_integral<typename remove_cv<T>::type> {}; 144 145 template <typename T> 146 inline constexpr bool is_integral_v = is_integral<T>::value; 147 148 template <typename T> 149 struct is_arithmetic 150 : bool_constant<is_integral_v<T> || is_floating_point_v<T>> {}; 151 152 template <typename T> 153 inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value; 154 155 #define __cpp_lib_is_null_pointer 201309L 156 157 template <typename T> 158 struct is_null_pointer : false_type {}; 159 160 template <> 161 struct is_null_pointer<decltype(nullptr)> : true_type {}; 162 163 template <typename T> 164 inline constexpr bool is_null_pointer_v = is_null_pointer<T>::value; 165 166 template <typename T> 167 struct is_pointer : false_type {}; 168 169 template <typename T> 170 struct is_pointer<T*> : true_type {}; 171 172 template <typename T> 173 inline constexpr bool is_pointer_v = is_pointer<T>::value; 174 175 template <typename T, typename U> 176 struct is_same : false_type {}; 177 178 template <typename T> 179 struct is_same<T, T> : true_type {}; 180 181 template <typename T, typename U> 182 inline constexpr bool is_same_v = is_same<T, U>::value; 183 184 namespace impl { 185 186 template <typename T, bool = is_arithmetic<T>::value> 187 struct is_signed : integral_constant<bool, T(-1) < T(0)> {}; 188 189 template <typename T> 190 struct is_signed<T, false> : false_type {}; 191 192 } // namespace impl 193 194 template <typename T> 195 struct is_signed : impl::is_signed<T>::type {}; 196 197 template <typename T> 198 inline constexpr bool is_signed_v = is_signed<T>::value; 199 200 template <typename T> 201 struct is_unsigned : bool_constant<!is_signed_v<T>> {}; 202 203 template <typename T> 204 inline constexpr bool is_unsigned_v = is_unsigned<T>::value; 205 206 template <typename T> 207 struct is_void : is_same<void, typename remove_cv<T>::type> {}; 208 209 template <typename T> 210 inline constexpr bool is_void_v = is_void<T>::value; 211 212 template <typename T> 213 struct negation : bool_constant<!bool(T::value)> {}; 214 215 template <typename T> 216 inline constexpr bool negation_v = negation<T>::value; 217 218 template <bool kBool, typename TrueType, typename FalseType> 219 struct conditional { 220 using type = TrueType; 221 }; 222 223 template <typename TrueType, typename FalseType> 224 struct conditional<false, TrueType, FalseType> { 225 using type = FalseType; 226 }; 227 228 template <bool kBool, typename TrueType, typename FalseType> 229 using conditional_t = typename conditional<kBool, TrueType, FalseType>::type; 230 231 template <bool kEnable, typename T = void> 232 struct enable_if { 233 using type = T; 234 }; 235 236 template <typename T> 237 struct enable_if<false, T> {}; 238 239 template <bool kEnable, typename T = void> 240 using enable_if_t = typename enable_if<kEnable, T>::type; 241 242 template <typename T> 243 struct remove_const { 244 using type = T; 245 }; 246 247 template <typename T> 248 struct remove_const<const T> { 249 using type = T; 250 }; 251 252 template <typename T> 253 using remove_const_t = typename remove_const<T>::type; 254 255 template <typename T> 256 struct remove_volatile { 257 using type = T; 258 }; 259 260 template <typename T> 261 struct remove_volatile<volatile T> { 262 using type = T; 263 }; 264 265 template <typename T> 266 using remove_volatile_t = typename remove_volatile<T>::type; 267 268 template <typename T> 269 struct remove_cv { 270 using type = remove_volatile_t<remove_const_t<T>>; 271 }; 272 273 template <typename T> 274 using remove_cv_t = typename remove_cv<T>::type; 275 276 template <typename T> 277 struct remove_extent { 278 using type = T; 279 }; 280 281 template <typename T> 282 struct remove_extent<T[]> { 283 using type = T; 284 }; 285 286 template <typename T, decltype(sizeof(0)) kSize> 287 struct remove_extent<T[kSize]> { 288 using type = T; 289 }; 290 291 template <typename T> 292 using remove_extent_t = typename remove_extent<T>::type; 293 294 template <typename T> 295 struct remove_pointer { 296 using type = T; 297 }; 298 299 template <typename T> 300 struct remove_pointer<T*> { 301 using type = T; 302 }; 303 304 template <typename T> 305 struct remove_pointer<T* const> { 306 using type = T; 307 }; 308 309 template <typename T> 310 struct remove_pointer<T* volatile> { 311 using type = T; 312 }; 313 314 template <typename T> 315 struct remove_pointer<T* const volatile> { 316 using type = T; 317 }; 318 319 template <typename T> 320 using remove_pointer_t = typename remove_pointer<T>::type; 321 322 template <typename T> 323 struct remove_reference { 324 using type = T; 325 }; 326 327 template <typename T> 328 struct remove_reference<T&> { 329 using type = T; 330 }; 331 332 template <typename T> 333 struct remove_reference<T&&> { 334 using type = T; 335 }; 336 337 template <typename T> 338 using remove_reference_t = typename remove_reference<T>::type; 339 340 // NOT IMPLEMENTED: This implementation is INCOMPLETE, as it does not cover 341 // function types. 342 template <typename T> 343 struct decay { 344 private: 345 using U = remove_reference_t<T>; 346 347 public: 348 using type = 349 conditional_t<is_array<U>::value, remove_extent_t<U>*, remove_cv_t<U>>; 350 }; 351 352 template <typename T> 353 using decay_t = typename decay<T>::type; 354 355 #define __cpp_lib_type_identity 201806 356 357 template <class T> 358 struct type_identity { 359 using type = T; 360 }; 361 362 template <typename T> 363 using type_identity_t = typename type_identity<T>::type; 364 365 #define __cpp_lib_void_t void_t 201411L 366 367 template <typename...> 368 using void_t = void; 369 370 namespace impl { 371 372 template <typename T> 373 type_identity<T&> AddLValueReference(int); 374 375 template <typename T> 376 type_identity<T> AddLValueReference(...); 377 378 template <typename T> 379 type_identity<T&&> AddRValueReference(int); 380 381 template <typename T> 382 type_identity<T> AddRValueReference(...); 383 384 } // namespace impl 385 386 template <class T> 387 struct add_lvalue_reference : decltype(impl::AddLValueReference<T>(0)) {}; 388 389 template <typename T> 390 using add_lvalue_reference_t = typename add_lvalue_reference<T>::type; 391 392 template <class T> 393 struct add_rvalue_reference : decltype(impl::AddRValueReference<T>(0)) {}; 394 395 template <typename T> 396 using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; 397 398 template <typename T> 399 add_rvalue_reference_t<T> declval() noexcept; 400 401 namespace impl { 402 403 template <typename> 404 using templated_true = true_type; 405 406 template <typename T> 407 auto returnable(int) -> templated_true<T()>; 408 409 template <typename> 410 auto returnable(...) -> false_type; 411 412 template <typename From, typename To> 413 auto convertible(int) 414 -> templated_true<decltype(declval<void (&)(To)>()(declval<From>()))>; 415 416 template <typename, typename> 417 auto convertible(...) -> false_type; 418 419 } // namespace impl 420 421 template <typename From, typename To> 422 struct is_convertible 423 : bool_constant<(decltype(impl::returnable<To>(0))() && 424 decltype(impl::convertible<From, To>(0))()) || 425 (is_void_v<From> && is_void_v<To>)> {}; 426 427 template <typename T, typename U> 428 inline constexpr bool is_convertible_v = is_convertible<T, U>::value; 429 430 // NOT IMPLEMENTED: Stubs are provided for these traits classes, but they do not 431 // return useful values. Many of these would require compiler builtins. 432 template <typename T> 433 struct is_function : false_type {}; 434 template <typename T> 435 struct is_trivially_copyable : true_type {}; 436 template <typename T> 437 struct is_polymorphic : false_type {}; 438 template <typename T, typename U> 439 struct is_base_of : false_type {}; 440 template <typename T> 441 struct extent : integral_constant<decltype(sizeof(int)), 1> {}; 442 template <typename T> 443 inline constexpr bool extent_v = extent<T>::value; 444 template <typename T> 445 struct underlying_type { 446 using type = T; 447 }; 448 template <typename T> 449 using underlying_type_t = typename underlying_type<T>::type; 450 template <typename T> 451 inline constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value; 452 453 _PW_POLYFILL_END_NAMESPACE_STD 454