• 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_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