• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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