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