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_type_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::is_one_of<T, TTypes...>
275 {
276 };
277
278 template <typename T>
279 struct type_list_contains<type_list<>, T> : public etl::bool_constant<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 template <typename TTypeList, size_t... Indices>
392 using type_list_select_from_indexes = type_list_select<TTypeList, Indices...>;
393
394 template <typename TTypeList, size_t... Indices>
395 using type_list_select_from_indexes_t = typename type_list_select<TTypeList, Indices...>::type;
396
397 //***************************************************************************
400 //***************************************************************************
401 template <typename TTypeList, typename TIndexSequence>
402 struct type_list_select_from_index_sequence;
403
404 template <typename TTypeList, size_t... Indices>
405 struct type_list_select_from_index_sequence<TTypeList, etl::index_sequence<Indices...>>
406 {
407 using type = etl::type_list_select_t<TTypeList, Indices...>;
408 };
409
410 template <typename TTypeList, typename TIndexSequence>
411 using type_list_select_from_index_sequence_t = typename type_list_select_from_index_sequence<TTypeList, TIndexSequence>::type;
412
413 //***************************************************************************
415 //***************************************************************************
416 template <typename... TTypes>
417 struct type_list_cat;
418
419 // The general case, concatenate the first two type_lists, then recurse with
420 // the result and the rest of the type_lists.
421 template <typename... TTypes1, typename... TTypes2, typename... TTail>
422 struct type_list_cat<etl::type_list<TTypes1...>, etl::type_list<TTypes2...>, TTail...>
423 {
424 using type = typename type_list_cat<etl::type_list<TTypes1..., TTypes2...>, TTail...>::type;
425 };
426
427 template <typename T>
428 struct type_list_cat<T>
429 {
430 using type = T;
431 };
432
433 template <>
434 struct type_list_cat<>
435 {
436 using type = etl::type_list<>;
437 };
438
439 template <typename... TypeLists>
440 using type_list_cat_t = typename type_list_cat<TypeLists...>::type;
441
442 //***************************************************************************
444 //***************************************************************************
445 template <typename T, typename... TTypes>
446 struct type_list_push_front;
447
448 template <typename T, typename... TTypes>
449 struct type_list_push_front<etl::type_list<TTypes...>, T>
450 {
451 using type = type_list<T, TTypes...>;
452 };
453
454 template <typename TypeList, typename T>
455 using type_list_push_front_t = typename type_list_push_front<TypeList, T>::type;
456
457 //***************************************************************************
459 //***************************************************************************
460 template <typename T, typename... TTypes>
461 struct type_list_push_back;
462
463 template <typename T, typename... TTypes>
464 struct type_list_push_back<etl::type_list<TTypes...>, T>
465 {
466 using type = type_list<TTypes..., T>;
467 };
468
469 template <typename TypeList, typename T>
470 using type_list_push_back_t = typename type_list_push_back<TypeList, T>::type;
471
472 //***************************************************************************
476 //***************************************************************************
477 template <typename TTypeList, typename T, size_t Index>
478 struct type_list_insert
479 {
480 private:
481
482 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
483 ETL_STATIC_ASSERT(Index <= TTypeList::size, "Index out of range");
484
485 using index_sequence_for_prefix = etl::make_index_sequence<Index>;
486 using index_sequence_for_suffix = etl::make_index_sequence_with_offset<Index, TTypeList::size - Index>;
487
488 using prefix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_prefix>;
489 using suffix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_suffix>;
490
491 public:
492
493 // Concatenate the prefix, new type, and suffix to create the new type list
494 // with T inserted at the correct position.
495 using type = etl::type_list_cat_t<prefix, etl::type_list<T>, suffix>;
496 };
497
498 #if ETL_USING_CPP11
499 template <typename TTypeList, typename T, size_t Index>
500 using type_list_insert_t = typename etl::type_list_insert<TTypeList, T, Index>::type;
501 #endif
502
503 //***************************************************************************
505 //***************************************************************************
506 template <typename TTypeList, size_t Index>
507 struct type_list_remove
508 {
509 private:
510
511 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
512 ETL_STATIC_ASSERT(Index < TTypeList::size, "Index out of range");
513
514 using index_sequence_for_prefix = etl::make_index_sequence<Index>;
515 using index_sequence_for_suffix = etl::make_index_sequence_with_offset<Index + 1, TTypeList::size - Index - 1>;
516
517 using prefix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_prefix>;
518 using suffix = etl::type_list_select_from_index_sequence_t<TTypeList, index_sequence_for_suffix>;
519
520 public:
521
522 // Concatenate the prefix and suffix to create the new type list with the
523 // Index element removed.
524 using type = etl::type_list_cat_t<prefix, suffix>;
525 };
526
527 #if ETL_USING_CPP11
528 template <typename TTypeList, size_t Index>
529 using type_list_remove_t = typename etl::type_list_remove<TTypeList, Index>::type;
530 #endif
531
532 //***************************************************************************
533 // Remove types that satisfy a predicate from a type_list.
534 //***************************************************************************
535 namespace private_type_list
536 {
537 template <typename TTypeList, template <typename> class TPredicate>
538 struct type_list_remove_if_impl;
539
540 template <template <typename> class TPredicate>
541 struct type_list_remove_if_impl<etl::type_list<>, TPredicate>
542 {
543 using type = etl::type_list<>;
544 };
545
546 template <typename Head, typename... Tail, template <typename> class TPredicate>
547 struct type_list_remove_if_impl<etl::type_list<Head, Tail...>, TPredicate>
548 {
549 private:
550
551 using rest = typename type_list_remove_if_impl<etl::type_list<Tail...>, TPredicate>::type;
552
553 public:
554
555 using type = typename etl::conditional< TPredicate<Head>::value, rest, etl::type_list_push_front_t<rest, Head>>::type;
556 };
557 } // namespace private_type_list
558
559 //***************************************************************************
563 //***************************************************************************
564 template <typename TTypeList, template <typename> class TPredicate>
565 struct type_list_remove_if
566 {
567 private:
568
569 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
570
571 public:
572
573 using type = typename private_type_list::type_list_remove_if_impl<TTypeList, TPredicate>::type;
574 };
575
576 #if ETL_USING_CPP11
577 template <typename TTypeList, template <typename> class TPredicate>
578 using type_list_remove_if_t = typename etl::type_list_remove_if<TTypeList, TPredicate>::type;
579 #endif
580
581 //***************************************************************************
583 //***************************************************************************
584 template <typename TTypeList>
585 struct type_list_pop_front
586 {
587 private:
588
589 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
590 ETL_STATIC_ASSERT(TTypeList::size > 0U, "Cannot pop_front from an empty type_list");
591
592 public:
593
594 using type = typename TTypeList::tail;
595 };
596
597 #if ETL_USING_CPP11
598 template <typename TTypeList>
599 using type_list_pop_front_t = typename etl::type_list_pop_front<TTypeList>::type;
600 #endif
601
602 //***************************************************************************
604 //***************************************************************************
605 template <typename TTypeList>
606 struct type_list_pop_back
607 {
608 private:
609
610 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
611 ETL_STATIC_ASSERT(TTypeList::size > 0U, "Cannot pop_back from an empty type_list");
612
613 public:
614
615 using type = typename etl::type_list_remove<TTypeList, TTypeList::size - 1U>::type;
616 };
617
618 #if ETL_USING_CPP11
619 template <typename TTypeList>
620 using type_list_pop_back_t = typename etl::type_list_pop_back<TTypeList>::type;
621 #endif
622
623 //***************************************************************************
624 // Remove duplicate types from a type_list, preserving the first occurrence.
625 //***************************************************************************
626 namespace private_type_list
627 {
628 template <typename TTypeList, typename TResult>
629 struct type_list_unique_impl;
630
631 // Base case: empty list, return the result.
632 template <typename TResult>
633 struct type_list_unique_impl<etl::type_list<>, TResult>
634 {
635 using type = TResult;
636 };
637
638 // Recursive case: Check if the head is already in the result, if not add
639 // it, then recurse on the tail.
640 template <typename Head, typename... Tail, typename TResult>
641 struct type_list_unique_impl<etl::type_list<Head, Tail...>, TResult>
642 {
643 private:
644
645 using next_result = etl::conditional_t<etl::type_list_contains<TResult, Head>::value, TResult, etl::type_list_push_back_t<TResult, Head>>;
646
647 public:
648
649 using type = typename type_list_unique_impl<etl::type_list<Tail...>, next_result>::type;
650 };
651 } // namespace private_type_list
652
653 //***************************************************************************
656 //***************************************************************************
657 template <typename TTypeList>
658 struct type_list_unique
659 {
660 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
661
662 using type = typename private_type_list::type_list_unique_impl<TTypeList, etl::type_list<>>::type;
663 };
664
665 #if ETL_USING_CPP11
666 template <typename TTypeList>
667 using type_list_unique_t = typename etl::type_list_unique<TTypeList>::type;
668 #endif
669
670 //***************************************************************************
672 //***************************************************************************
673 template <typename TTypeList>
674 struct type_list_is_unique
675 // Create a unique version of the type list, and check if it is the same as
676 // the original list. If they are the same, then all types in the original
677 // list are unique.
678 : etl::bool_constant< etl::is_same< TTypeList, typename type_list_unique<TTypeList>::type>::value>
679 {
680 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
681 };
682
683 #if ETL_USING_CPP17
684 template <typename TTypeList>
685 inline constexpr bool type_list_is_unique_v = etl::type_list_is_unique<TTypeList>::value;
686 #endif
687
688 //***************************************************************************
690 //***************************************************************************
691 template <typename T>
692 struct type_list_is_empty;
693
694 template <>
695 struct type_list_is_empty<etl::type_list<>> : etl::true_type
696 {
697 };
698
699 template <typename... TTypes>
700 struct type_list_is_empty<etl::type_list<TTypes...>> : etl::false_type
701 {
702 };
703
704 #if ETL_USING_CPP17
705 template <typename... TTypes>
706 inline constexpr bool type_list_is_empty_v = type_list_is_empty<TTypes...>::value;
707 #endif
708
709 //***************************************************************************
713 //***************************************************************************
714 template <typename TTypeList, template <typename> class TPredicate>
715 struct type_list_all_of;
716
717 template <template <typename> class TPredicate, typename... TTypes>
718 struct type_list_all_of<etl::type_list<TTypes...>, TPredicate> : etl::conjunction<TPredicate<TTypes>...>
719 {
720 };
721
722 #if ETL_USING_CPP17
723 template <typename TTypeList, template <typename> class TPredicate>
724 inline constexpr bool type_list_all_of_v = type_list_all_of<TTypeList, TPredicate>::value;
725 #endif
726
727 //***************************************************************************
731 //***************************************************************************
732 template <typename TTypeList, template <typename> class TPredicate>
733 struct type_list_any_of;
734
735 template <template <typename> class TPredicate, typename... TTypes>
736 struct type_list_any_of<etl::type_list<TTypes...>, TPredicate> : etl::disjunction<TPredicate<TTypes>...>
737 {
738 };
739
740 #if ETL_USING_CPP17
741 template <typename TTypeList, template <typename> class TPredicate>
742 inline constexpr bool type_list_any_of_v = type_list_any_of<TTypeList, TPredicate>::value;
743 #endif
744
745 //***************************************************************************
749 //***************************************************************************
750 template <typename TTypeList, template <typename> class TPredicate>
751 struct type_list_none_of;
752
753 template <template <typename> class TPredicate, typename... TTypes>
754 struct type_list_none_of<etl::type_list<TTypes...>, TPredicate> : etl::negation<etl::disjunction<TPredicate<TTypes>...>>
755 {
756 };
757
758 #if ETL_USING_CPP17
759 template <typename TTypeList, template <typename> class TPredicate>
760 inline constexpr bool type_list_none_of_v = type_list_none_of<TTypeList, TPredicate>::value;
761 #endif
762
763 //***************************************************************************
766 //***************************************************************************
767 // Primary template
768 template <typename TFromList, typename TToList>
769 struct type_lists_are_convertible;
770
771 // Specialization: both lists empty, convertible
772 template <>
773 struct type_lists_are_convertible<etl::type_list<>, etl::type_list<>> : public etl::true_type
774 {
775 };
776
777 // Recursive case: check head types, then recurse
778 template <typename TFromHead, typename... TFromTail, typename TToHead, typename... TToTail>
779 struct type_lists_are_convertible<etl::type_list<TFromHead, TFromTail...>, etl::type_list<TToHead, TToTail...>>
780 : public etl::bool_constant< etl::is_convertible<TFromHead, TToHead>::value
781 && etl::type_lists_are_convertible< etl::type_list<TFromTail...>, etl::type_list<TToTail...>>::value>
782 {
783 static_assert(sizeof...(TFromTail) == sizeof...(TToTail), "Type lists are not the same length");
784 };
785
786 #if ETL_USING_CPP17
787 template <typename TFromList, typename TToList>
788 inline constexpr bool type_lists_are_convertible_v = etl::type_lists_are_convertible<TFromList, TToList>::value;
789 #endif
790
791 namespace private_type_list
792 {
793 //*********************************
794 template <typename TTypeList, template <typename, typename> class TCompare>
795 struct type_list_is_sorted_impl;
796
797 //*********************************
798 // Empty list is sorted
799 template <template <typename, typename> class TCompare>
800 struct type_list_is_sorted_impl<etl::type_list<>, TCompare> : etl::true_type
801 {
802 };
803
804 //*********************************
805 // Single element list is sorted
806 template <typename T0, template <typename, typename> class TCompare>
807 struct type_list_is_sorted_impl<etl::type_list<T0>, TCompare> : etl::true_type
808 {
809 };
810
811 //*********************************
812 // Ensure that the list is sorted.
813 // Recursively compare the head to the next element to ensure that the list
814 // is sorted.
815 template <typename Head, typename Next, typename... Tail, template <typename, typename> class TCompare>
816 struct type_list_is_sorted_impl<etl::type_list<Head, Next, Tail...>, TCompare>
817 : etl::bool_constant< !TCompare<Next, Head>::value && type_list_is_sorted_impl< etl::type_list<Next, Tail...>, TCompare>::value>
818 {
819 };
820 } // namespace private_type_list
821
822 //*****************************************************************************
827 //*****************************************************************************
828 template <typename TTypeList, template <typename, typename> class TCompare>
829 struct type_list_is_sorted : public private_type_list::type_list_is_sorted_impl<TTypeList, TCompare>
830 {
831 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
832 };
833
834 #if ETL_USING_CPP17
835 template <typename TTypeList, template <typename, typename> class TCompare>
836 inline constexpr bool type_list_is_sorted_v = etl::type_list_is_sorted<TTypeList, TCompare>::value;
837 #endif
838
839 //*****************************************************************************
840 namespace private_type_list
841 {
842 //*********************************
843 template <bool InsertBefore, typename Head, typename T, template <typename, typename> class TCompare, typename... Tail>
844 struct insert_sorted_impl;
845
846 //*********************************
847 template <typename TSortedList, typename T, template <typename, typename> class TCompare>
848 struct type_list_insert_sorted_impl;
849
850 //*********************************
851 // Insert T into sorted list using TCompare
852 // Empty list -> T becomes the list
853 template <typename T, template <typename, typename> class TCompare>
854 struct type_list_insert_sorted_impl<etl::type_list<>, T, TCompare>
855 {
856 using type = etl::type_list<T>;
857 };
858
859 //*********************************
860 // Insert T into the correct position in the sorted list, as determined by
861 // TCompare
862 template <typename Head, typename... Tail, typename T, template <typename, typename> class TCompare>
863 struct type_list_insert_sorted_impl<etl::type_list<Head, Tail...>, T, TCompare>
864 {
865 using type = typename insert_sorted_impl<TCompare<T, Head>::value, Head, T, TCompare, Tail...>::type;
866 };
867
868 //*********************************
869 // If InsertBefore is true, then T should be inserted before Head
870 template <typename Head, typename T, template <typename, typename> class TCompare, typename... Tail>
871 struct insert_sorted_impl<true, Head, T, TCompare, Tail...>
872 {
873 using type = etl::type_list<T, Head, Tail...>;
874 };
875
876 //*********************************
877 // If InsertBefore is false, then T should be inserted after Head, so we
878 // recursively call insert_sorted_impl on the tail of the list
879 template <typename Head, typename T, template <typename, typename> class TCompare, typename... Tail>
880 struct insert_sorted_impl<false, Head, T, TCompare, Tail...>
881 {
882 using type = etl::type_list_push_front_t< typename type_list_insert_sorted_impl<etl::type_list<Tail...>, T, TCompare>::type, Head>;
883 };
884 } // namespace private_type_list
885
886 //*****************************************************************************
891 //*****************************************************************************
892 template <typename TTypeList, typename T, template <typename, typename> class TCompare>
893 struct type_list_insert_sorted : public private_type_list::type_list_insert_sorted_impl<TTypeList, T, TCompare>
894 {
895 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
896 ETL_STATIC_ASSERT((etl::type_list_is_sorted<TTypeList, TCompare>::value), "Cannot insert into a non-sorted type list");
897 };
898
899 #if ETL_USING_CPP11
900 template <typename TTypeList, typename T, template <typename, typename> class TCompare>
901 using type_list_insert_sorted_t = typename etl::type_list_insert_sorted<TTypeList, T, TCompare>::type;
902 #endif
903
904 //***************************************************************************
905 namespace private_type_list
906 {
907 //*********************************
908 // Forward declaration
909 template <typename TTypeList, template <typename, typename> class TCompare>
910 struct type_list_sort_impl;
911
912 //*********************************
913 // Empty list
914 template <template <typename, typename> class TCompare>
915 struct type_list_sort_impl<etl::type_list<>, TCompare>
916 {
917 using type = etl::type_list<>;
918 };
919
920 //*********************************
921 // Single element list
922 template <typename T0, template <typename, typename> class TCompare>
923 struct type_list_sort_impl<etl::type_list<T0>, TCompare>
924 {
925 using type = etl::type_list<T0>;
926 };
927
928 //*********************************
929 // Define a new type_list by sorting the types according to TCompare
930 template <typename Head, typename... Tail, template <typename, typename> class TCompare>
931 struct type_list_sort_impl<etl::type_list<Head, Tail...>, TCompare>
932 {
933 private:
934
935 using sorted_tail = typename type_list_sort_impl<etl::type_list<Tail...>, TCompare>::type;
936
937 public:
938
939 using type = typename etl::type_list_insert_sorted<sorted_tail, Head, TCompare>::type;
940 };
941 } // namespace private_type_list
942
943 //*****************************************************************************
947 //*****************************************************************************
948 template <typename TTypeList, template <typename, typename> class TCompare>
949 struct type_list_sort : public private_type_list::type_list_sort_impl<TTypeList, TCompare>
950 {
951 ETL_STATIC_ASSERT((etl::is_type_list<TTypeList>::value), "TTypeList must be an etl::type_list");
952 };
953
954 #if ETL_USING_CPP11
955 template <typename TTypeList, template <typename, typename> class TCompare>
956 using type_list_sort_t = typename etl::type_list_sort<TTypeList, TCompare>::type;
957 #endif
958
959 //*****************************************************************************
962 //*****************************************************************************
963 template <typename T, typename... TypeLists>
964 struct type_list_in_all_lists : etl::conjunction<etl::type_list_contains<TypeLists, T>...>
965 {
966 };
967
968 // Specialisation if no lists provided.
969 template <typename T>
970 struct type_list_in_all_lists<T> : etl::false_type
971 {
972 };
973
974 #if ETL_USING_CPP17
975 template <typename T, typename... TypeLists>
976 inline constexpr bool type_list_in_all_lists_v = type_list_in_all_lists<T, TypeLists...>::value;
977 #endif
978
979 //*****************************************************************************
982 //*****************************************************************************
983 template <typename T, typename... TypeLists>
984 struct type_list_in_any_list : etl::false_type
985 {
986 };
987
988 // Recursive case: Check the first list using your helper.
989 template <typename T, typename FirstList, typename... RestLists>
990 struct type_list_in_any_list<T, FirstList, RestLists...>
991 : etl::conditional<type_list_contains<FirstList, T>::value, etl::true_type, type_list_in_any_list<T, RestLists...>>::type
992 {
993 };
994
995 #if ETL_USING_CPP17
996 template <typename T, typename... TypeLists>
997 inline constexpr bool type_list_in_any_list_v = type_list_in_any_list<T, TypeLists...>::value;
998 #endif
999
1000 //*****************************************************************************
1003 //*****************************************************************************
1004 template <typename T, typename... Lists>
1005 using type_list_in_no_lists = etl::bool_constant<!type_list_in_any_list<T, Lists...>::value>;
1006
1007 #if ETL_USING_CPP17
1008 template <typename T, typename... Lists>
1009 inline constexpr bool type_list_in_no_lists_v = type_list_in_no_lists<T, Lists...>::value;
1010 #endif
1011
1012 //*****************************************************************************
1013 namespace private_type_list
1014 {
1015 template <typename TInputList, typename TAccumulatedResult, typename... TOtherLists>
1016 struct type_list_remove_from_accumulator;
1017
1018 // Base case: No more types to process, return the accumulated result.
1019 template <typename TAccumulatedResult, typename... TOtherLists>
1020 struct type_list_remove_from_accumulator<etl::type_list<>, TAccumulatedResult, TOtherLists...>
1021 {
1022 using type = TAccumulatedResult;
1023 };
1024
1025 // Recursive case: Process Head, accumulate result forward.
1026 template <typename Head, typename... Tail, typename TAccumulatedResult, typename... TOtherLists>
1027 struct type_list_remove_from_accumulator<etl::type_list<Head, Tail...>, TAccumulatedResult, TOtherLists...>
1028 {
1029 private:
1030
1031 // Check if Head does not exist in any of the other lists.
1032 static constexpr bool head_is_not_in_other_lists = etl::type_list_in_no_lists<Head, TOtherLists...>::value;
1033
1034 // Append Head to the result if it's NOT in any of the other lists.
1035 using accumulated = etl::conditional_t<head_is_not_in_other_lists, etl::type_list_push_back_t<TAccumulatedResult, Head>, TAccumulatedResult>;
1036
1037 public:
1038
1039 // Recurse with the updated accumulator and remaining types.
1040 using type = typename type_list_remove_from_accumulator<etl::type_list<Tail...>, accumulated, TOtherLists...>::type;
1041 };
1042
1043 //*****************************************************************************
1044 // Extract the first list and call the main implementation.
1045 //*****************************************************************************
1046 template <typename... TypeLists>
1047 struct type_list_remove_from_helper;
1048
1049 // An difference of no type_lists is an empty type_list.
1050 template <>
1051 struct type_list_remove_from_helper<>
1052 {
1053 using type = etl::type_list<>;
1054 };
1055
1056 // One list, so just return it.
1057 template <typename TypeList>
1058 struct type_list_remove_from_helper<TypeList>
1059 {
1060 using type = TypeList;
1061 };
1062
1063 // Two or more lists.
1064 template <typename TFirstList, typename... TRestLists>
1065 struct type_list_remove_from_helper<TFirstList, TRestLists...>
1066 {
1067 using type = typename type_list_remove_from_accumulator<TFirstList, etl::type_list<>, TRestLists...>::type;
1068 };
1069 } // namespace private_type_list
1070
1071 //***************************************************************************
1075 //***************************************************************************
1076 template <typename... TypeLists>
1077 struct type_list_remove_from
1078 {
1079 // Ensure all parameters are actually type_lists.
1080 static_assert(etl::conjunction<etl::is_type_list<TypeLists>...>::value, "All parameters must be etl::type_list types");
1081
1082 using type = typename private_type_list::type_list_remove_from_helper<TypeLists...>::type;
1083 };
1084
1085 template <typename... TypeLists>
1086 using type_list_remove_from_t = typename type_list_remove_from<TypeLists...>::type;
1087
1088 //***************************************************************************
1090 //***************************************************************************
1091 template <typename... TypeLists>
1092 struct type_list_cat_unique
1093 {
1094 // Ensure all parameters are actually type_lists (optional, but helpful).
1095 static_assert(etl::conjunction<etl::is_type_list<TypeLists>...>::value, "All parameters must be etl::type_list types");
1096
1097 using type = etl::type_list_unique_t<type_list_cat_t<TypeLists...>>;
1098 };
1099
1100 template <typename... TypeLists>
1101 using type_list_cat_unique_t = typename type_list_cat_unique<TypeLists...>::type;
1102
1103 //****************************************************************************
1104 namespace private_type_list
1105 {
1106 template <typename TInputList, typename TAccumulatedResult, typename... TOtherLists>
1107 struct type_list_select_common_types_accumulator;
1108
1109 // Base case: No more types to process, return the accumulated result.
1110 template <typename TAccumulatedResult, typename... TOtherLists>
1111 struct type_list_select_common_types_accumulator<etl::type_list<>, TAccumulatedResult, TOtherLists...>
1112 {
1113 using type = TAccumulatedResult;
1114 };
1115
1116 // Recursive case: Process Head, accumulate result forward.
1117 template <typename Head, typename... Tail, typename TAccumulatedResult, typename... TOtherLists>
1118 struct type_list_select_common_types_accumulator<etl::type_list<Head, Tail...>, TAccumulatedResult, TOtherLists...>
1119 {
1120 private:
1121
1122 // Check if Head exists in all other lists.
1123 static constexpr bool head_is_in_all_lists = etl::type_list_in_all_lists<Head, TOtherLists...>::value;
1124
1125 // Append Head to the result if it's in all lists AND not already added.
1126 using accumulated = etl::conditional_t<head_is_in_all_lists, etl::type_list_push_back_t<TAccumulatedResult, Head>, TAccumulatedResult>;
1127
1128 public:
1129
1130 // Recurse with the updated accumulator and remaining types.
1131 using type = typename type_list_select_common_types_accumulator<etl::type_list<Tail...>, accumulated, TOtherLists...>::type;
1132 };
1133
1134 //*****************************************************************************
1135 // Extract the first list and call the main implementation.
1136 //*****************************************************************************
1137 template <typename... TypeLists>
1138 struct type_list_select_common_types_helper;
1139
1140 // An intersection of no type lists is an empty type_list.
1141 template <>
1142 struct type_list_select_common_types_helper<>
1143 {
1144 using type = etl::type_list<>;
1145 };
1146
1147 // One list, so just return it.
1148 template <typename TypeList>
1149 struct type_list_select_common_types_helper<TypeList>
1150 {
1151 using type = etl::type_list_unique_t<TypeList>;
1152 };
1153
1154 // Two or more lists, use the intersection algorithm.
1155 template <typename TFirstList, typename... TRestLists>
1156 struct type_list_select_common_types_helper<TFirstList, TRestLists...>
1157 {
1158 private:
1159
1160 // Remove duplicates from the first list.
1161 using first_unique = etl::type_list_unique_t<TFirstList>;
1162
1163 public:
1164
1165 using type = typename type_list_select_common_types_accumulator<first_unique, etl::type_list<>, TRestLists...>::type;
1166 };
1167 } // namespace private_type_list
1168
1169 //*****************************************************************************
1173 //*****************************************************************************
1174 template <typename... TypeLists>
1175 struct type_list_select_common_types
1176 {
1177 // Ensure all parameters are actually type_lists (optional, but helpful).
1178 static_assert(etl::conjunction<etl::is_type_list<TypeLists>...>::value, "All parameters must be etl::type_list types");
1179
1180 using type = typename private_type_list::type_list_select_common_types_helper<TypeLists...>::type;
1181 };
1182
1183 template <typename... TypeLists>
1184 using type_list_select_common_types_t = typename type_list_select_common_types<TypeLists...>::type;
1185
1186 //*****************************************************************************
1190 //*****************************************************************************
1191 template <typename... TypeLists>
1192 struct type_list_select_not_common_types
1193 {
1194 // Ensure all parameters are actually type_lists (optional, but helpful).
1195 static_assert(etl::conjunction<etl::is_type_list<TypeLists>...>::value, "All parameters must be etl::type_list types");
1196
1197 using type = etl::type_list_remove_from_t<etl::type_list_cat_unique_t<TypeLists...>, etl::type_list_select_common_types_t<TypeLists...>>;
1198 };
1199
1200 template <typename... TypeLists>
1201 using type_list_select_not_common_types_t = typename type_list_select_not_common_types<TypeLists...>::type;
1202
1203} // namespace etl
1204#endif
1205
1206#endif
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:1434