Embedded Template Library 1.0
Loading...
Searching...
No Matches
type_list.h
1/******************************************************************************
2The MIT License(MIT)
3
4Embedded Template Library.
5https://github.com/ETLCPP/etl
6https://www.etlcpp.com
7
8Copyright(c) 2025 John Wellbelove
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files(the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions :
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27******************************************************************************/
28
29#ifndef ETL_TYPE_LIST_INCLUDED
30#define ETL_TYPE_LIST_INCLUDED
31
32#include "platform.h"
33
34#include "index_of_type.h"
35#include "integral_limits.h"
36#include "largest.h"
37#include "static_assert.h"
38#include "type_traits.h"
39#include "utility.h"
40
41#if ETL_USING_CPP11
42namespace etl
43{
44 //***************************************************************************
46 //***************************************************************************
47 static ETL_CONSTANT size_t type_list_npos = etl::integral_limits<size_t>::max;
48
49 //***************************************************************************
50 // Type list forward declaration.
51 //***************************************************************************
52 template <typename... TTypes>
53 struct type_list;
54
55 //***************************************************************************
57 //***************************************************************************
58 template <typename T>
59 struct is_type_list : etl::false_type
60 {
61 };
62
63 template <typename... TTypes>
64 struct is_type_list<etl::type_list<TTypes...>> : etl::true_type
65 {
66 };
67
68 #if ETL_USING_CPP17
69 template <typename T>
70 inline constexpr bool is_type_list_v = is_type_list<T>::value;
71 #endif
72
73 //***************************************************************************
75 //***************************************************************************
76 template <>
77 struct type_list<>
78 {
79 static constexpr size_t size = 0U;
80
81 using index_sequence_type = etl::make_index_sequence<0>;
83
84 private:
85
86 // A type_list cannot be instantiated, so delete the constructor and
87 // assignment operators.
88 type_list() ETL_DELETE;
89 type_list(const type_list&) ETL_DELETE;
90 type_list& operator=(const type_list&) ETL_DELETE;
91 };
92
93 namespace private_type_list
94 {
95 // helper to solve the issue that recursed-rest can't be put directly in
96 // type_list::tail definition
97 template <typename... TTypes>
98 struct recursion_helper
99 {
100 using type = type_list<TTypes...>;
101 };
102 } // namespace private_type_list
103
104 //***************************************************************************
106 //***************************************************************************
107 template <typename THead, typename... TTail>
108 struct type_list<THead, TTail...> : type_list<TTail...>
109 {
110 using head = THead;
111 using tail = typename private_type_list::recursion_helper<TTail...>::type;
112
113 static constexpr size_t size = sizeof...(TTail) + 1U;
114
115 using index_sequence_type = etl::make_index_sequence< sizeof...(TTail) + 1U>;
116
117 private:
118
119 // A type_list cannot be instantiated, so delete the constructor and
120 // assignment operators.
121 type_list() ETL_DELETE;
122 type_list(const type_list&) ETL_DELETE;
123 type_list& operator=(const type_list&) ETL_DELETE;
124 };
125
126 //***************************************************************************
128 //***************************************************************************
129 template <typename THead>
130 struct type_list<THead> : type_list<>
131 {
132 using head = THead;
133 using tail = typename private_type_list::recursion_helper<>::type;
134
135 static constexpr size_t size = 1U;
136
137 using index_sequence_type = etl::make_index_sequence<1>;
139
140 private:
141
142 type_list() ETL_DELETE;
143 type_list(const type_list&) ETL_DELETE;
144 type_list& operator=(const type_list&) ETL_DELETE;
145 };
146
147 //***************************************************************************
149 //***************************************************************************
150 template <typename TTypes>
151 struct type_list_size;
152
153 template <typename... TTypes>
154 struct type_list_size<etl::type_list<TTypes...>> : public etl::integral_constant<size_t, sizeof...(TTypes)>
155 {
156 };
157
158 #if ETL_USING_CPP17
159 template <typename... TTypes>
160 inline constexpr size_t type_list_size_v = type_list_size<etl::type_list<TTypes...>>::value;
161 #endif
162
163 //***************************************************************************
166 //***************************************************************************
167 template <typename TTypeList, size_t Index>
168 struct type_list_type_at_index
169 {
170 ETL_STATIC_ASSERT(Index < TTypeList::size, "etl::type_list_type_at_index out of range");
171 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
172
173 using type = typename type_list_type_at_index<typename TTypeList::tail, Index - 1>::type;
174 };
175
176 template <typename TTypeList>
177 struct type_list_type_at_index<TTypeList, 0>
178 {
179 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
180
181 using type = typename TTypeList::head;
182 };
183
184 template <typename TTypeList, size_t Index>
185 using type_list_type_at_index_t = typename type_list_type_at_index<TTypeList, Index>::type;
186
187 //***************************************************************************
193 //***************************************************************************
194 template <typename TTypeList, typename T>
195 struct type_list_index_of_type
196 : public etl::integral_constant< size_t, etl::is_same<typename TTypeList::head, T>::value
197 ? 0
198 : (type_list_index_of_type<typename TTypeList::tail, T>::value == etl::type_list_npos
199 ? etl::type_list_npos
200 : type_list_index_of_type<typename TTypeList::tail, T>::value + 1)>
201 {
202 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
203 };
204
205 template <typename T>
206 struct type_list_index_of_type<type_list<>, T> : public etl::integral_constant<size_t, etl::type_list_npos>
207 {
208 };
209
210 #if ETL_USING_CPP17
211 template <typename TTypeList, typename T>
212 inline constexpr size_t type_list_index_of_v = etl::type_list_index_of_type<TTypeList, T>::value;
213 #endif
214
215 //***************************************************************************
221 //***************************************************************************
222 namespace private_type_list
223 {
224 template <typename TTypeList, typename T, size_t Index, typename TResult>
225 struct type_list_indices_of_type_impl;
226
227 // The general case, check the head type, then recurse with the rest of the
228 // types.
229 template <typename Head, typename... Tail, typename T, size_t Index, typename TResult>
230 struct type_list_indices_of_type_impl<etl::type_list<Head, Tail...>, T, Index, TResult>
231 {
232 private:
233
234 // If Head is the same as T then append a new index to the result,
235 // otherwise no change.
236 using next_result = etl::conditional_t<etl::is_same<Head, T>::value, etl::index_sequence_push_back_t<TResult, Index>, TResult>;
237
238 public:
239
240 // Recurse with the rest of the type_list, passing on the current result.
241 using type = typename type_list_indices_of_type_impl<etl::type_list<Tail...>, T, Index + 1U, next_result>::type;
242 };
243
244 // Specialisation for an empty type_list.
245 // This is the terminating specialisation for the general case.
246 template <typename T, size_t Index, typename TResult>
247 struct type_list_indices_of_type_impl<etl::type_list<>, T, Index, TResult>
248 {
249 using type = TResult;
250 };
251 } // namespace private_type_list
252
253 template <typename TTypeList, typename T>
254 struct type_list_indices_of_type
255 {
256 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
257
258 using type = typename private_type_list::type_list_indices_of_type_impl< TTypeList, T, 0U, etl::index_sequence<>>::type;
259 };
260
261 #if ETL_USING_CPP11
262 template <typename TTypeList, typename T>
263 using type_list_indices_of_type_t = typename type_list_indices_of_type<TTypeList, T>::type;
264 #endif
265
266 //***************************************************************************
269 //***************************************************************************
270 template <typename TTypeList, typename T>
271 struct type_list_contains;
272
273 template <typename T, typename... TTypes>
274 struct type_list_contains<etl::type_list<TTypes...>, T> : public etl::integral_constant<bool, etl::is_one_of<T, TTypes...>::value>
275 {
276 };
277
278 template <typename T>
279 struct type_list_contains<type_list<>, T> : public etl::integral_constant<bool, false>
280 {
281 };
282
283 #if ETL_USING_CPP17
284 template <typename TTypeList, typename T>
285 inline constexpr bool type_list_contains_v = etl::type_list_contains<TTypeList, T>::value;
286 #endif
287
288 //***************************************************************************
291 //***************************************************************************
292 template <typename TTypeList, typename T>
293 struct type_list_has_duplicates_of;
294
295 template <typename T, typename... TTypes>
296 struct type_list_has_duplicates_of<etl::type_list<TTypes...>, T> : public etl::has_duplicates_of<T, TTypes...>
297 {
298 };
299
300 template <typename T>
301 struct type_list_has_duplicates_of<type_list<>, T> : public etl::integral_constant<bool, false>
302 {
303 };
304
305 #if ETL_USING_CPP17
306 template <typename TTypeList, typename T>
307 inline constexpr bool type_list_has_duplicates_of_v = etl::type_list_has_duplicates_of<TTypeList, T>::value;
308 #endif
309
310 //***************************************************************************
313 //***************************************************************************
314 template <typename TTypeList, typename T>
315 struct type_list_count_of;
316
317 template <typename T, typename... TTypes>
318 struct type_list_count_of<etl::type_list<TTypes...>, T> : public etl::count_of<T, TTypes...>
319 {
320 };
321
322 template <typename T>
323 struct type_list_count_of<type_list<>, T> : public etl::integral_constant<size_t, 0>
324 {
325 };
326
327 #if ETL_USING_CPP17
328 template <typename TTypeList, typename T>
329 inline constexpr size_t type_list_count_of_v = etl::type_list_count_of<TTypeList, T>::value;
330 #endif
331
332 //***************************************************************************
335 //***************************************************************************
336 template <typename T>
337 struct type_list_max_size;
338
339 template <typename... TTypes>
340 struct type_list_max_size<etl::type_list<TTypes...>> : public etl::integral_constant<size_t, etl::largest<TTypes...>::size>
341 {
342 };
343
344 template <>
345 struct type_list_max_size<type_list<>> : public etl::integral_constant<size_t, 0>
346 {
347 };
348
349 #if ETL_USING_CPP17
350 template <typename TTypeList>
351 inline constexpr size_t type_list_max_size_v = etl::type_list_max_size<TTypeList>::value;
352 #endif
353
354 //***************************************************************************
357 //***************************************************************************
358 template <typename T>
359 struct type_list_max_alignment;
360
361 template <typename... TTypes>
362 struct type_list_max_alignment<etl::type_list<TTypes...>> : public etl::integral_constant<size_t, etl::largest<TTypes...>::alignment>
363 {
364 };
365
366 template <>
367 struct type_list_max_alignment<type_list<>> : public etl::integral_constant<size_t, 1>
368 {
369 };
370
371 #if ETL_USING_CPP17
372 template <typename TTypeList>
373 inline constexpr size_t type_list_max_alignment_v = etl::type_list_max_alignment<TTypeList>::value;
374 #endif
375
376 //***************************************************************************
379 //***************************************************************************
380 template <typename TTypeList, size_t... Indices>
381 struct type_list_select
382 {
383 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
384
385 using type = type_list<type_list_type_at_index_t<TTypeList, Indices>...>;
386 };
387
388 template <typename TTypeList, size_t... Indices>
389 using type_list_select_t = typename type_list_select<TTypeList, Indices...>::type;
390
391 //***************************************************************************
394 //***************************************************************************
395 template <typename TTypeList, typename TIndexSequence>
396 struct type_list_select_from_index_sequence;
397
398 template <typename TTypeList, size_t... Indices>
399 struct type_list_select_from_index_sequence<TTypeList, etl::index_sequence<Indices...>>
400 {
401 using type = etl::type_list_select_t<TTypeList, Indices...>;
402 };
403
404 template <typename TTypeList, typename TIndexSequence>
405 using type_list_select_from_index_sequence_t = typename type_list_select_from_index_sequence<TTypeList, TIndexSequence>::type;
406
407 //***************************************************************************
409 //***************************************************************************
410 template <typename... TTypes>
411 struct type_list_cat;
412
413 template <typename... TTypes1, typename... TTypes2, typename... TTail>
414 struct type_list_cat<etl::type_list<TTypes1...>, etl::type_list<TTypes2...>, TTail...>
415 {
416 using type = typename type_list_cat<etl::type_list<TTypes1..., TTypes2...>, TTail...>::type;
417 };
418
419 template <typename T>
420 struct type_list_cat<T>
421 {
422 using type = T;
423 };
424
425 template <typename... TypeLists>
426 using type_list_cat_t = typename type_list_cat<TypeLists...>::type;
427
428 //***************************************************************************
430 //***************************************************************************
431 template <typename T, typename... TTypes>
432 struct type_list_push_front;
433
434 template <typename T, typename... TTypes>
435 struct type_list_push_front<etl::type_list<TTypes...>, T>
436 {
437 using type = type_list<T, TTypes...>;
438 };
439
440 template <typename TypeList, typename T>
441 using type_list_push_front_t = typename type_list_push_front<TypeList, T>::type;
442
443 //***************************************************************************
445 //***************************************************************************
446 template <typename T, typename... TTypes>
447 struct type_list_push_back;
448
449 template <typename T, typename... TTypes>
450 struct type_list_push_back<etl::type_list<TTypes...>, T>
451 {
452 using type = type_list<TTypes..., T>;
453 };
454
455 template <typename TypeList, typename T>
456 using type_list_push_back_t = typename type_list_push_back<TypeList, T>::type;
457
458 //***************************************************************************
462 //***************************************************************************
463 template <typename TTypeList, typename T, size_t Index>
464 struct type_list_insert
465 {
466 private:
467
468 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
469 ETL_STATIC_ASSERT(Index <= TTypeList::size, "Index out of range");
470
471 using index_sequence_for_prefix = etl::make_index_sequence<Index>;
472 using index_sequence_for_suffix = etl::make_index_sequence_with_offset<Index, TTypeList::size - Index>;
473
474 using prefix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_prefix>;
475 using suffix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_suffix>;
476
477 public:
478
479 // Concatenate the prefix, new type, and suffix to create the new type list
480 // with T inserted at the correct position.
481 using type = etl::type_list_cat_t<prefix, etl::type_list<T>, suffix>;
482 };
483
484 #if ETL_USING_CPP11
485 template <typename TTypeList, typename T, size_t Index>
486 using type_list_insert_t = typename etl::type_list_insert<TTypeList, T, Index>::type;
487 #endif
488
489 //***************************************************************************
491 //***************************************************************************
492 template <typename TTypeList, size_t Index>
493 struct type_list_remove
494 {
495 private:
496
497 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
498 ETL_STATIC_ASSERT(Index < TTypeList::size, "Index out of range");
499
500 using index_sequence_for_prefix = etl::make_index_sequence<Index>;
501 using index_sequence_for_suffix = etl::make_index_sequence_with_offset<Index + 1, TTypeList::size - Index - 1>;
502
503 using prefix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_prefix>;
504 using suffix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_suffix>;
505
506 public:
507
508 // Concatenate the prefix and suffix to create the new type list with the
509 // Index element removed.
510 using type = etl::type_list_cat_t<prefix, suffix>;
511 };
512
513 #if ETL_USING_CPP11
514 template <typename TTypeList, size_t Index>
515 using type_list_remove_t = typename etl::type_list_remove<TTypeList, Index>::type;
516 #endif
517
518 //***************************************************************************
519 // Remove types that satisfy a predicate from a type_list.
520 //***************************************************************************
521 namespace private_type_list
522 {
523 template <typename TTypeList, template <typename> class TPredicate>
524 struct type_list_remove_if_impl;
525
526 template <template <typename> class TPredicate>
527 struct type_list_remove_if_impl<etl::type_list<>, TPredicate>
528 {
529 using type = etl::type_list<>;
530 };
531
532 template <typename Head, typename... Tail, template <typename> class TPredicate>
533 struct type_list_remove_if_impl<etl::type_list<Head, Tail...>, TPredicate>
534 {
535 private:
536
537 using rest = typename type_list_remove_if_impl<etl::type_list<Tail...>, TPredicate>::type;
538
539 public:
540
541 using type = typename etl::conditional< TPredicate<Head>::value, rest, etl::type_list_push_front_t<rest, Head>>::type;
542 };
543 } // namespace private_type_list
544
545 //***************************************************************************
549 //***************************************************************************
550 template <typename TTypeList, template <typename> class TPredicate>
551 struct type_list_remove_if
552 {
553 private:
554
555 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
556
557 public:
558
559 using type = typename private_type_list::type_list_remove_if_impl<TTypeList, TPredicate>::type;
560 };
561
562 #if ETL_USING_CPP11
563 template <typename TTypeList, template <typename> class TPredicate>
564 using type_list_remove_if_t = typename etl::type_list_remove_if<TTypeList, TPredicate>::type;
565 #endif
566
567 //***************************************************************************
569 //***************************************************************************
570 template <typename TTypeList>
571 struct type_list_pop_front
572 {
573 private:
574
575 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
576 ETL_STATIC_ASSERT(TTypeList::size > 0U, "Cannot pop_front from an empty type_list");
577
578 public:
579
580 using type = typename TTypeList::tail;
581 };
582
583 #if ETL_USING_CPP11
584 template <typename TTypeList>
585 using type_list_pop_front_t = typename etl::type_list_pop_front<TTypeList>::type;
586 #endif
587
588 //***************************************************************************
590 //***************************************************************************
591 template <typename TTypeList>
592 struct type_list_pop_back
593 {
594 private:
595
596 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
597 ETL_STATIC_ASSERT(TTypeList::size > 0U, "Cannot pop_back from an empty type_list");
598
599 public:
600
601 using type = typename etl::type_list_remove<TTypeList, TTypeList::size - 1U>::type;
602 };
603
604 #if ETL_USING_CPP11
605 template <typename TTypeList>
606 using type_list_pop_back_t = typename etl::type_list_pop_back<TTypeList>::type;
607 #endif
608
609 //***************************************************************************
610 // Remove duplicate types from a type_list, preserving the first occurrence.
611 //***************************************************************************
612 namespace private_type_list
613 {
614 template <typename TTypeList, typename TResult>
615 struct type_list_unique_impl;
616
617 // Base case: empty list, return the result.
618 template <typename TResult>
619 struct type_list_unique_impl<etl::type_list<>, TResult>
620 {
621 using type = TResult;
622 };
623
624 // Recursive case: Check if the head is already in the result, if not add
625 // it, then recurse on the tail.
626 template <typename Head, typename... Tail, typename TResult>
627 struct type_list_unique_impl<etl::type_list<Head, Tail...>, TResult>
628 {
629 private:
630
631 using next_result = etl::conditional_t<etl::type_list_contains<TResult, Head>::value, TResult, etl::type_list_push_back_t<TResult, Head>>;
632
633 public:
634
635 using type = typename type_list_unique_impl<etl::type_list<Tail...>, next_result>::type;
636 };
637 } // namespace private_type_list
638
639 //***************************************************************************
642 //***************************************************************************
643 template <typename TTypeList>
644 struct type_list_unique
645 {
646 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
647
648 using type = typename private_type_list::type_list_unique_impl<TTypeList, etl::type_list<>>::type;
649 };
650
651 #if ETL_USING_CPP11
652 template <typename TTypeList>
653 using type_list_unique_t = typename etl::type_list_unique<TTypeList>::type;
654 #endif
655
656 //***************************************************************************
658 //***************************************************************************
659 template <typename TTypeList>
660 struct type_list_is_unique
661 // Create a unique version of the type list, and check if it is the same as
662 // the original list. If they are the same, then all types in the original
663 // list are unique.
664 : etl::bool_constant< etl::is_same< TTypeList, typename type_list_unique<TTypeList>::type>::value>
665 {
666 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
667 };
668
669 #if ETL_USING_CPP17
670 template <typename TTypeList>
671 inline constexpr bool type_list_is_unique_v = etl::type_list_is_unique<TTypeList>::value;
672 #endif
673
674 //***************************************************************************
676 //***************************************************************************
677 template <typename T>
678 struct type_list_is_empty;
679
680 template <>
681 struct type_list_is_empty<etl::type_list<>> : etl::true_type
682 {
683 };
684
685 template <typename... TTypes>
686 struct type_list_is_empty<etl::type_list<TTypes...>> : etl::false_type
687 {
688 };
689
690 #if ETL_USING_CPP17
691 template <typename... TTypes>
692 inline constexpr bool type_list_is_empty_v = type_list_is_empty<TTypes...>::value;
693 #endif
694
695 //***************************************************************************
699 //***************************************************************************
700 template <typename TTypeList, template <typename> class TPredicate>
701 struct type_list_all_of;
702
703 template <template <typename> class TPredicate, typename... TTypes>
704 struct type_list_all_of<etl::type_list<TTypes...>, TPredicate> : etl::conjunction<TPredicate<TTypes>...>
705 {
706 };
707
708 template <template <typename> class TPredicate>
709 struct type_list_all_of<etl::type_list<>, TPredicate> : etl::bool_constant<true>
710 {
711 };
712
713 #if ETL_USING_CPP17
714 template <typename TTypeList, template <typename> class TPredicate>
715 inline constexpr bool type_list_all_of_v = type_list_all_of<TTypeList, TPredicate>::value;
716 #endif
717
718 //***************************************************************************
722 //***************************************************************************
723 template <typename TTypeList, template <typename> class TPredicate>
724 struct type_list_any_of;
725
726 template <template <typename> class TPredicate, typename... TTypes>
727 struct type_list_any_of<etl::type_list<TTypes...>, TPredicate> : etl::disjunction<TPredicate<TTypes>...>
728 {
729 };
730
731 template <template <typename> class TPredicate>
732 struct type_list_any_of<etl::type_list<>, TPredicate> : etl::bool_constant<false>
733 {
734 };
735
736 #if ETL_USING_CPP17
737 template <typename TTypeList, template <typename> class TPredicate>
738 inline constexpr bool type_list_any_of_v = type_list_any_of<TTypeList, TPredicate>::value;
739 #endif
740
741 //***************************************************************************
745 //***************************************************************************
746 template <typename TTypeList, template <typename> class TPredicate>
747 struct type_list_none_of;
748
749 template <template <typename> class TPredicate, typename... TTypes>
750 struct type_list_none_of<etl::type_list<TTypes...>, TPredicate> : etl::negation<etl::disjunction<TPredicate<TTypes>...>>
751 {
752 };
753
754 template <template <typename> class TPredicate>
755 struct type_list_none_of<etl::type_list<>, TPredicate> : etl::bool_constant<true>
756 {
757 };
758
759 #if ETL_USING_CPP17
760 template <typename TTypeList, template <typename> class TPredicate>
761 inline constexpr bool type_list_none_of_v = type_list_none_of<TTypeList, TPredicate>::value;
762 #endif
763
764 //***************************************************************************
767 //***************************************************************************
768 // Primary template
769 template <typename TFromList, typename TToList>
770 struct type_lists_are_convertible;
771
772 // Specialization: both lists empty, convertible
773 template <>
774 struct type_lists_are_convertible<etl::type_list<>, etl::type_list<>> : public etl::true_type
775 {
776 };
777
778 // Recursive case: check head types, then recurse
779 template <typename TFromHead, typename... TFromTail, typename TToHead, typename... TToTail>
780 struct type_lists_are_convertible<etl::type_list<TFromHead, TFromTail...>, etl::type_list<TToHead, TToTail...>>
781 : public etl::bool_constant< etl::is_convertible<TFromHead, TToHead>::value
782 && etl::type_lists_are_convertible< etl::type_list<TFromTail...>, etl::type_list<TToTail...>>::value>
783 {
784 static_assert(sizeof...(TFromTail) == sizeof...(TToTail), "Type lists are not the same length");
785 };
786
787 #if ETL_USING_CPP17
788 template <typename TFromList, typename TToList>
789 inline constexpr bool type_lists_are_convertible_v = etl::type_lists_are_convertible<TFromList, TToList>::value;
790 #endif
791
792 namespace private_type_list
793 {
794 //*********************************
795 template <typename TTypeList, template <typename, typename> class TCompare>
796 struct type_list_is_sorted_impl;
797
798 //*********************************
799 // Empty list is sorted
800 template <template <typename, typename> class TCompare>
801 struct type_list_is_sorted_impl<etl::type_list<>, TCompare> : etl::true_type
802 {
803 };
804
805 //*********************************
806 // Single element list is sorted
807 template <typename T0, template <typename, typename> class TCompare>
808 struct type_list_is_sorted_impl<etl::type_list<T0>, TCompare> : etl::true_type
809 {
810 };
811
812 //*********************************
813 // Ensure that the list is sorted.
814 // Recursively compare the head to the next element to ensure that the list
815 // is sorted.
816 template <typename Head, typename Next, typename... Tail, template <typename, typename> class TCompare>
817 struct type_list_is_sorted_impl<etl::type_list<Head, Next, Tail...>, TCompare>
818 : etl::bool_constant< !TCompare<Next, Head>::value && type_list_is_sorted_impl< etl::type_list<Next, Tail...>, TCompare>::value>
819 {
820 };
821 } // namespace private_type_list
822
823 //*****************************************************************************
828 //*****************************************************************************
829 template <typename TTypeList, template <typename, typename> class TCompare>
830 struct type_list_is_sorted : public private_type_list::type_list_is_sorted_impl<TTypeList, TCompare>
831 {
832 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
833 };
834
835 #if ETL_USING_CPP17
836 template <typename TTypeList, template <typename, typename> class TCompare>
837 inline constexpr bool type_list_is_sorted_v = etl::type_list_is_sorted<TTypeList, TCompare>::value;
838 #endif
839
840 //*****************************************************************************
841 namespace private_type_list
842 {
843 //*********************************
844 template <bool InsertBefore, typename Head, typename T, template <typename, typename> class TCompare, typename... Tail>
845 struct insert_sorted_impl;
846
847 //*********************************
848 template <typename TSortedList, typename T, template <typename, typename> class TCompare>
849 struct type_list_insert_sorted_impl;
850
851 //*********************************
852 // Insert T into sorted list using TCompare
853 // Empty list -> T becomes the list
854 template <typename T, template <typename, typename> class TCompare>
855 struct type_list_insert_sorted_impl<etl::type_list<>, T, TCompare>
856 {
857 using type = etl::type_list<T>;
858 };
859
860 //*********************************
861 // Insert T into the correct position in the sorted list, as determined by
862 // TCompare
863 template <typename Head, typename... Tail, typename T, template <typename, typename> class TCompare>
864 struct type_list_insert_sorted_impl<etl::type_list<Head, Tail...>, T, TCompare>
865 {
866 using type = typename insert_sorted_impl<TCompare<T, Head>::value, Head, T, TCompare, Tail...>::type;
867 };
868
869 //*********************************
870 // If InsertBefore is true, then T should be inserted before Head
871 template <typename Head, typename T, template <typename, typename> class TCompare, typename... Tail>
872 struct insert_sorted_impl<true, Head, T, TCompare, Tail...>
873 {
874 using type = etl::type_list<T, Head, Tail...>;
875 };
876
877 //*********************************
878 // If InsertBefore is false, then T should be inserted after Head, so we
879 // recursively call insert_sorted_impl on the tail of the list
880 template <typename Head, typename T, template <typename, typename> class TCompare, typename... Tail>
881 struct insert_sorted_impl<false, Head, T, TCompare, Tail...>
882 {
883 using type = etl::type_list_push_front_t< typename type_list_insert_sorted_impl<etl::type_list<Tail...>, T, TCompare>::type, Head>;
884 };
885 } // namespace private_type_list
886
887 //*****************************************************************************
892 //*****************************************************************************
893 template <typename TTypeList, typename T, template <typename, typename> class TCompare>
894 struct type_list_insert_sorted : public private_type_list::type_list_insert_sorted_impl<TTypeList, T, TCompare>
895 {
896 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
897 ETL_STATIC_ASSERT((etl::type_list_is_sorted<TTypeList, TCompare>::value), "Cannot insert into a non-sorted type list");
898 };
899
900 #if ETL_USING_CPP11
901 template <typename TTypeList, typename T, template <typename, typename> class TCompare>
902 using type_list_insert_sorted_t = typename etl::type_list_insert_sorted<TTypeList, T, TCompare>::type;
903 #endif
904
905 //***************************************************************************
906 namespace private_type_list
907 {
908 //*********************************
909 // Forward declaration
910 template <typename TTypeList, template <typename, typename> class TCompare>
911 struct type_list_sort_impl;
912
913 //*********************************
914 // Empty list
915 template <template <typename, typename> class TCompare>
916 struct type_list_sort_impl<etl::type_list<>, TCompare>
917 {
918 using type = etl::type_list<>;
919 };
920
921 //*********************************
922 // Single element list
923 template <typename T0, template <typename, typename> class TCompare>
924 struct type_list_sort_impl<etl::type_list<T0>, TCompare>
925 {
926 using type = etl::type_list<T0>;
927 };
928
929 //*********************************
930 // Define a new type_list by sorting the types according to TCompare
931 template <typename Head, typename... Tail, template <typename, typename> class TCompare>
932 struct type_list_sort_impl<etl::type_list<Head, Tail...>, TCompare>
933 {
934 private:
935
936 using sorted_tail = typename type_list_sort_impl<etl::type_list<Tail...>, TCompare>::type;
937
938 public:
939
940 using type = typename etl::type_list_insert_sorted<sorted_tail, Head, TCompare>::type;
941 };
942 } // namespace private_type_list
943
944 //*****************************************************************************
948 //*****************************************************************************
949 template <typename TTypeList, template <typename, typename> class TCompare>
950 struct type_list_sort : public private_type_list::type_list_sort_impl<TTypeList, TCompare>
951 {
952 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
953 };
954
955 #if ETL_USING_CPP11
956 template <typename TTypeList, template <typename, typename> class TCompare>
957 using type_list_sort_t = typename etl::type_list_sort<TTypeList, TCompare>::type;
958 #endif
959} // namespace etl
960#endif
961
962#endif
bitset_ext
Definition absolute.h:40
integral_constant< bool, false > false_type
integral_constant specialisations
Definition type_traits.h:80
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1192