BlueToe
an alternative GATT/BLE implementation
Loading...
Searching...
No Matches
meta_tools.hpp
Go to the documentation of this file.
1#ifndef BLUETOE_META_TOOLS_HPP
2#define BLUETOE_META_TOOLS_HPP
3
4#include <utility>
5#include <type_traits>
6#include <tuple>
7
12namespace bluetoe {
13namespace details {
14
15 template < typename T >
16 struct wrap {
17 using type = T;
18 };
19
21 template < bool Select >
22 struct select_type_impl {
23 template < typename A, typename B >
24 using f = A;
25 };
26
27 template <>
28 struct select_type_impl< false > {
29 template < typename A, typename B >
30 using f = B;
31 };
37 template < bool Select, typename A, typename B >
38 using select_type = wrap< typename select_type_impl< Select >::template f< A, B > >;
39
46 template < bool Select, template < typename > class A, template < typename > class B >
47 struct select_template_t1 {
48 template < typename T1 >
49 using type = A< T1 >;
50 };
51
52 template < template < typename > class A, template < typename > class B >
53 struct select_template_t1< false, A, B > {
54 template < typename T1 >
55 using type = B< T1 >;
56 };
57
59 template < typename Null, typename A >
60 struct or_type_impl {
61 template < typename >
62 using f = A;
63 };
64
65 template < typename Null >
66 struct or_type_impl< Null, Null > {
67 template < typename B >
68 using f = B;
69 };
75 template < typename Null, typename A, typename B >
76 using or_type = wrap< typename or_type_impl< Null, A >::template f< B > >;
77
81 template < class A, class B >
82 struct add_type
83 {
84 typedef std::tuple< A, B > type;
85 };
86
87 template < class T, class ... Ts >
88 struct add_type< T, std::tuple< Ts... > >
89 {
90 typedef std::tuple< T, Ts... > type;
91 };
92
93 template < class ...Ts, class T >
94 struct add_type< std::tuple< Ts... >, T >
95 {
96 typedef std::tuple< Ts..., T > type;
97 };
98
99 template < class ...As, class ...Bs >
100 struct add_type< std::tuple< As... >, std::tuple< Bs...> >
101 {
102 typedef std::tuple< As..., Bs... > type;
103 };
104
105 /*
106 * wildcard to be used when templates should be used within remove_if_equal
107 */
108 struct wildcard {};
109
110 /*
111 * Removes from a typelist (std::tuple) all elments that are equal to Zero
112 */
113 template < typename A, typename Zero >
114 struct remove_if_equal;
115
116 template < typename Zero >
117 struct remove_if_equal< std::tuple<>, Zero >
118 {
119 typedef std::tuple<> type;
120 };
121
122 template <
123 typename Type,
124 typename Zero
125 >
126 struct remove_if_equal< std::tuple< Type >, Zero >
127 {
128 typedef std::tuple< Type > type;
129 };
130
131 // two types are equal if they are the same types
132 template <
133 typename Zero
134 >
135 struct remove_if_equal< std::tuple< Zero >, Zero >
136 {
137 typedef std::tuple<> type;
138 };
139
140 // two types are equal if they are both templates and the Zero type has it's parameters replaces with wildcards
141 template <
142 template < typename ... > class Templ,
143 typename Type
144 >
145 struct remove_if_equal< std::tuple< Templ< Type > >, Templ< wildcard > >
146 {
147 typedef std::tuple<> type;
148 };
149
150 template <
151 typename Type,
152 typename ... Types,
153 typename Zero
154 >
155 struct remove_if_equal< std::tuple< Type, Types... >, Zero >
156 {
157 typedef typename add_type<
158 typename remove_if_equal< std::tuple< Type >, Zero >::type,
159 typename remove_if_equal< std::tuple< Types... >, Zero >::type
160 >::type type;
161 };
162
163 /*
164 * a tuple type with two elements
165 */
166 template < typename A, typename B >
167 struct pair {
168 typedef A first_type;
169 typedef B second_type;
170 };
171
172 template < typename T >
173 struct not_type
174 {
175 typedef std::integral_constant< bool, !T::value > type;
176 };
177
178 /*
179 * empty result
180 */
181 struct no_such_type {};
182
183 /*
184 * Last element from typelist or Default if list is empty
185 */
186 template < typename T, typename Default = no_such_type >
187 struct last_type;
188
189 template < typename Default >
190 struct last_type< std::tuple<>, Default >
191 {
192 using type = Default;
193 };
194
195 template < typename T, typename Default >
196 struct last_type< std::tuple< T >, Default >
197 {
198 using type = T;
199 };
200
201 template < typename ...Ts, typename T, typename Default >
202 struct last_type< std::tuple< T, Ts... >, Default >
203 {
204 using type = typename last_type< std::tuple< Ts... >, Default >::type;
205 };
206
207 template < typename T >
208 struct extract_meta_type
209 {
210 template < class U >
211 static typename U::meta_type check( U&& ) { return U::meta_type(); }
212 static no_such_type check( ... ) { return no_such_type(); }
213
214 typedef decltype( check( std::declval< T >() ) ) meta_type;
215 typedef meta_type type;
216 typedef typename not_type<
217 typename std::is_same<
218 meta_type, no_such_type >::type >::type has_meta_type;
219 };
220
221 /*
222 * finds the first type that has the embedded meta_type
223 */
224 template <
225 typename MetaType,
226 typename ... Types >
227 struct find_by_meta_type;
228
229 template <
230 typename MetaType >
231 struct find_by_meta_type< MetaType >
232 {
233 typedef no_such_type type;
234 };
235
236 template <
237 typename MetaType,
238 typename Type >
239 struct find_by_meta_type< MetaType, Type >
240 {
241 typedef extract_meta_type< Type > meta_type;
242 typedef typename select_type<
243 std::is_convertible< typename meta_type::type*, MetaType* >::value,
244 Type, no_such_type >::type type;
245 };
246
247 template <
248 typename MetaType,
249 typename Type,
250 typename ... Types >
251 struct find_by_meta_type< MetaType, Type, Types... >
252 {
253 typedef typename or_type<
254 no_such_type,
255 typename find_by_meta_type< MetaType, Type >::type,
256 typename find_by_meta_type< MetaType, Types... >::type >::type type;
257 };
258
259 /*
260 * finds the first type that has _not_ the embedded meta_type
261 */
262 template <
263 typename MetaType,
264 typename ... Types >
265 struct find_by_not_meta_type;
266
267 template <
268 typename MetaType >
269 struct find_by_not_meta_type< MetaType >
270 {
271 typedef no_such_type type;
272 };
273
274 template <
275 typename MetaType,
276 typename Type >
277 struct find_by_not_meta_type< MetaType, Type >
278 {
279 typedef extract_meta_type< Type > meta_type;
280 typedef typename select_type<
281 std::is_convertible< typename meta_type::type*, MetaType* >::value,
282 no_such_type, Type >::type type;
283 };
284
285 template <
286 typename MetaType,
287 typename Type,
288 typename ... Types >
289 struct find_by_not_meta_type< MetaType, Type, Types... >
290 {
291 typedef typename or_type<
292 no_such_type,
293 typename find_by_not_meta_type< MetaType, Type >::type,
294 typename find_by_not_meta_type< MetaType, Types... >::type >::type type;
295 };
296
297 /*
298 * finds all types that has the embedded meta_type
299 */
300 template <
301 typename MetaType,
302 typename ... Types >
303 struct find_all_by_meta_type;
304
305 template <
306 typename MetaType >
307 struct find_all_by_meta_type< MetaType >
308 {
309 typedef std::tuple<> type;
310 };
311
312 template <
313 typename MetaType,
314 typename Type,
315 typename ... Types >
316 struct find_all_by_meta_type< MetaType, Type, Types... >
317 {
318 typedef extract_meta_type< Type > meta_type;
319 typedef typename select_type<
320 std::is_convertible< typename meta_type::type*, MetaType* >::value,
321 typename add_type< Type, typename find_all_by_meta_type< MetaType, Types... >::type >::type,
322 typename find_all_by_meta_type< MetaType, Types... >::type >::type type;
323 };
324
325 template <
326 typename MetaType,
327 typename ... Types >
328 struct find_all_by_meta_type< MetaType, std::tuple< Types... > > : find_all_by_meta_type< MetaType, Types... > {};
329
330 /*
331 * finds all types that has not the embedded meta_type
332 */
333 template <
334 typename MetaType,
335 typename ... Types >
336 struct find_all_by_not_meta_type;
337
338 template <
339 typename MetaType >
340 struct find_all_by_not_meta_type< MetaType >
341 {
342 typedef std::tuple<> type;
343 };
344
345 template <
346 typename MetaType,
347 typename Type,
348 typename ... Types >
349 struct find_all_by_not_meta_type< MetaType, Type, Types... >
350 {
351 typedef extract_meta_type< Type > meta_type;
352 typedef typename select_type<
353 std::is_convertible< typename meta_type::type*, MetaType* >::value,
354 typename find_all_by_not_meta_type< MetaType, Types... >::type,
355 typename add_type< Type, typename find_all_by_not_meta_type< MetaType, Types... >::type >::type
356 >::type type;
357 };
358
359 template <
360 typename MetaType,
361 typename ... Types >
362 struct find_all_by_not_meta_type< MetaType, std::tuple< Types... > > : find_all_by_not_meta_type< MetaType, Types... > {};
363
364 /*
365 * groups a list of types by there meta types
366 *
367 * Returns a std::tuple with as much elements as MetaTypes where given. Every element in the result is a tuple containing
368 * the meta type followed by the result of a call to find_all_by_meta_type<>
369 */
370 template <
371 typename Types,
372 typename ... MetaTypes >
373 struct group_by_meta_types;
374
375 template <
376 typename ... Types >
377 struct group_by_meta_types< std::tuple< Types... > >
378 {
379 typedef std::tuple<> type;
380 };
381
382 template <
383 typename ... Types,
384 typename MetaType >
385 struct group_by_meta_types< std::tuple< Types... >, MetaType >
386 {
387 typedef std::tuple<
388 typename add_type<
389 MetaType,
390 typename find_all_by_meta_type< MetaType, Types... >::type
391 >::type
392 > type;
393 };
394
395 template <
396 typename ... Types,
397 typename MetaType,
398 typename ... MetaTypes >
399 struct group_by_meta_types< std::tuple< Types... >, MetaType, MetaTypes... >
400 {
401 typedef typename add_type<
402 typename group_by_meta_types< std::tuple< Types... >, MetaType >::type,
403 typename group_by_meta_types< std::tuple< Types... >, MetaTypes... >::type >::type type;
404 };
405
409 template <
410 typename Types,
411 typename ... MetaTypes >
412 struct group_by_meta_types_without_empty_groups;
413
414 template <
415 typename ... Types,
416 typename ... MetaTypes >
417 struct group_by_meta_types_without_empty_groups< std::tuple< Types... >, MetaTypes...>
418 {
419 typedef typename remove_if_equal<
420 typename group_by_meta_types< std::tuple< Types... >, MetaTypes... >::type,
421 std::tuple< wildcard >
422 >::type type;
423 };
424
425
426 /*
427 * counts the number of Types with a given MetaType
428 */
429 template <
430 typename MetaType,
431 typename ... Types >
432 struct count_by_meta_type;
433
434 template <
435 typename MetaType >
436 struct count_by_meta_type< MetaType > {
437 enum { count = 0 };
438 };
439
440 template <
441 typename MetaType,
442 typename Type,
443 typename ... Types >
444 struct count_by_meta_type< MetaType, Type, Types... > {
445 typedef extract_meta_type< Type > meta_type;
446
447 enum { count = std::is_convertible< typename meta_type::type*, MetaType* >::value
448 ? 1 + count_by_meta_type< MetaType, Types... >::count
449 : 0 + count_by_meta_type< MetaType, Types... >::count
450 };
451 };
452
453 /*
454 * counts the number of types, the predicate returned true for an element applied to it
455 */
456 template <
457 typename List,
458 template < typename > class Predicate
459 >
460 struct count_if;
461
462 template <
463 template < typename > class Predicate
464 >
465 struct count_if< std::tuple<>, Predicate > : std::integral_constant< int, 0 > {};
466
467 template <
468 typename T,
469 template < typename > class Predicate
470 >
471 struct count_if< std::tuple< T >, Predicate > : std::integral_constant< int, Predicate< T >::value ? 1 : 0 > {};
472
473 template <
474 typename T,
475 typename ...Ts,
476 template < typename > class Predicate
477 >
478 struct count_if< std::tuple< T, Ts... >, Predicate > : std::integral_constant< int,
479 count_if< std::tuple< T >, Predicate >::value
480 + count_if< std::tuple< Ts... >, Predicate >::value > {};
481
482 /*
483 * sums up the result of a call to Predicate with every element from List
484 */
485 template <
486 typename List,
487 template < typename > class Predicate
488 >
489 struct sum_by;
490
491 template <
492 template < typename > class Predicate
493 >
494 struct sum_by< std::tuple<>, Predicate > : std::integral_constant< int, 0 > {};
495
496 template <
497 typename T,
498 template < typename > class Predicate
499 >
500 struct sum_by< std::tuple< T >, Predicate > : std::integral_constant< int, Predicate< T >::value > {};
501
502 template <
503 typename T,
504 typename ...Ts,
505 template < typename > class Predicate
506 >
507 struct sum_by< std::tuple< T, Ts... >, Predicate > : std::integral_constant< int,
508 sum_by< std::tuple< T >, Predicate >::value
509 + sum_by< std::tuple< Ts... >, Predicate >::value > {};
510
514 template <
515 typename Option,
516 typename ... Options >
517 struct has_option;
518
519 template <
520 typename Option >
521 struct has_option< Option > {
522 static bool constexpr value = false;
523 };
524
525 template <
526 typename Option,
527 typename FirstOption,
528 typename ... Options >
529 struct has_option< Option, FirstOption, Options... > {
530 static bool constexpr value =
531 std::is_same< Option, FirstOption >::value || has_option< Option, Options... >::value;
532 };
533
555 template <
556 typename ... Options >
557 struct for_impl;
558
559 template <>
560 struct for_impl<>
561 {
562 template < typename Function >
563 static void each( Function )
564 {}
565 };
566
567 template <
568 typename Option,
569 typename ... Options >
570 struct for_impl< Option, Options... >
571 {
572 template < typename Function >
573 static void each( Function f )
574 {
575 f.template each< Option >();
576 for_impl< Options... >::template each< Function >( f );
577 }
578 };
579
580 template <
581 typename ... Options >
582 struct for_ : for_impl< Options... >
583 {
584 };
585
586 template <
587 typename ... Options >
588 struct for_< std::tuple< Options... > > : for_impl< Options... >
589 {
590 };
591
595 template <
596 typename List,
597 template < typename > class Func
598 >
599 struct find_if;
600
601 template <
602 template < typename > class Func
603 >
604 struct find_if< std::tuple<>, Func > {
605 typedef no_such_type type;
606 };
607
608 template <
609 typename T,
610 typename ... Ts,
611 template < typename > class Func
612 >
613 struct find_if< std::tuple< T, Ts...>, Func > {
614 typedef typename select_type<
615 Func< T >::value,
616 T,
617 typename find_if< std::tuple< Ts... >, Func >::type >::type type;
618 };
619
620
621 template < typename ... Ts >
622 struct last_from_pack;
623
624 template < typename T >
625 struct last_from_pack< T > {
626 typedef T type;
627 };
628
629 template <
630 typename T,
631 typename ... Ts >
632 struct last_from_pack< T, Ts... > {
633 typedef typename last_from_pack< Ts... >::type type;
634 };
635
636 // defines an empty type with the given meta_type
637 template < typename MetaType >
638 struct empty_meta_type {
639 typedef MetaType meta_type;
640 };
641
642 template < typename ... Ts >
643 struct derive_from_impl;
644
645 template <>
646 struct derive_from_impl<> {};
647
648 template < typename T, typename ... Ts >
649 struct derive_from_impl< T, Ts... > : T, derive_from_impl< Ts... > {};
650
651 // derives from all types within the given typelist List
652 template < typename List >
653 struct derive_from;
654
655 template < typename ... Ts >
656 struct derive_from< std::tuple< Ts... > > : derive_from_impl< Ts... > {};
657
658 // fold a list with an operation
659 template <
660 typename List,
661 template < typename ListP, typename ElementP > class Operation,
662 typename Start = std::tuple<> >
663 struct fold;
664
665 template <
666 template < typename List, typename Element > class Operation,
667 typename Start >
668 struct fold< std::tuple<>, Operation, Start >
669 {
670 typedef Start type;
671 };
672
673 template <
674 typename T,
675 typename ... Ts,
676 template < typename List, typename Element > class Operation,
677 typename Start >
678 struct fold< std::tuple< T, Ts... >, Operation, Start >
679 {
680 typedef typename Operation< typename fold< std::tuple< Ts... >, Operation, Start >::type, T >::type type;
681 };
682
683 template <
684 typename List,
685 template < typename ListP, typename ElementP > class Operation,
686 typename Start = std::tuple<> >
687 struct fold_right : fold< List, Operation, Start > {};
688
689
690 template <
691 typename List,
692 template < typename ListP, typename ElementP > class Operation,
693 typename Start = std::tuple<> >
694 struct fold_left;
695
696 template < bool >
697 struct fold_left_impl;
698
699 template <>
700 struct fold_left_impl< false > {
701 template <
702 template < typename, typename > class,
703 typename Start,
704 typename ... >
705 using f = Start;
706 };
707
708 template <>
709 struct fold_left_impl< true > {
710 template <
711 template < typename, typename > class Operation,
712 typename Start,
713 typename T,
714 typename ... Ts >
715 using f = typename fold_left_impl< sizeof...(Ts) != 0 >::template f< Operation, typename Operation< Start, T >::type, Ts... >;
716 };
717
718 template <
719 typename ... Ts,
720 template < typename ListP, typename ElementP > class Operation,
721 typename Start >
722 struct fold_left< std::tuple< Ts... >, Operation, Start > :
723 wrap< typename fold_left_impl< sizeof...(Ts) != 0 >::template f< Operation, Start, Ts... > >
724 {};
725
726 template < template < typename > class Transform >
727 struct apply_transformation
728 {
729 template < typename List, typename Element >
730 struct apply
731 {
732 using type = typename add_type< List, typename Transform< Element >::type >::type;
733 };
734 };
735
736 /*
737 * transform a list into an other list of the same length
738 */
739 template <
740 typename List,
741 template < typename > class Transform
742 >
743 struct transform_list : fold_left< List, apply_transformation< Transform >::template apply > {};
744
745 // for a T in Ts, find the index of T in Ts
746 // If T is not in Ts, the resulting value is sizeof...(Ts)
747 template < typename T, typename ... Ts >
748 struct index_of;
749
750 // not in list:
751 template < typename T, typename O >
752 struct index_of< T, O > {
753 static constexpr unsigned value = 1;
754 };
755
756 // not in empty list
757 template < typename T >
758 struct index_of< T > {
759 static constexpr unsigned value = 0;
760 };
761
762 template < typename T >
763 struct index_of< T, T > {
764 static constexpr unsigned value = 0;
765 };
766
767 template < typename T, typename ... Ts >
768 struct index_of< T, T, Ts... > {
769 static constexpr unsigned value = 0;
770 };
771
772 template < typename T, typename O, typename ... Ts >
773 struct index_of< T, O, Ts... > {
774 static constexpr unsigned value = index_of< T, Ts... >::value + 1;
775 };
776
777 template < typename T, typename ... Ts >
778 struct index_of< T, std::tuple< Ts... > > : index_of< T, Ts... > {};
779
780 /*
781 * Insert T into Ts at the first position, that satisfies Order
782 */
783 template < template < typename, typename > class Order, typename T, typename ...Ts >
784 struct stable_insert;
785
786 template < template < typename, typename > class Order, typename T, typename ...Ts >
787 struct stable_insert< Order, T, std::tuple< Ts... > > : stable_insert< Order, T, Ts... > {};
788
789 template < template < typename, typename > class Order, typename T >
790 struct stable_insert< Order, T >
791 {
792 using type = std::tuple< T >;
793 };
794
795 template < template < typename, typename > class Order, typename T, typename First, typename ...Ts >
796 struct stable_insert< Order, T, First, Ts... >
797 {
798 using type = typename select_type<
799 Order< First, T >::type::value,
800 typename add_type< First, typename stable_insert< Order, T, Ts... >::type >::type,
801 std::tuple< T, First, Ts... >
802 >::type;
803 };
804
805 /*
806 * stable sort a list of types based on a given order
807 *
808 * The order must take two types as argument and define type to be either std::true_type or std::false_type
809 */
810 template < template < typename, typename > class Order, typename ...Ts >
811 struct stable_sort;
812
813 template < template < typename, typename > class Order, typename ...Ts >
814 struct stable_sort< Order, std::tuple< Ts... > > : stable_sort< Order, Ts... > {};
815
816 template < template < typename, typename > class Order >
817 struct stable_sort< Order, std::tuple<> >
818 {
819 using type = std::tuple<>;
820 };
821
822 template < template < typename, typename > class Order >
823 struct stable_sort< Order >
824 {
825 using type = std::tuple<>;
826 };
827
828 template < template < typename, typename > class Order, typename T, typename ...Ts >
829 struct stable_sort< Order, T, Ts... >
830 {
831 using rest = typename stable_sort< Order, Ts... >::type;
832 using type = typename stable_insert< Order, T, rest >::type;
833 };
834
835 /*
836 * A map is a std::tuple< pair< Key, Value > >
837 */
838
839 // Returns the Value to the Key or no_such_type, if not found
840 template < typename Map, typename Key, typename Default = no_such_type >
841 struct map_find;
842
843 template < typename Key, typename Default >
844 struct map_find< std::tuple<>, Key, Default >
845 {
846 using type = Default;
847 };
848
849 template < typename Value, typename Key, typename ...Ts, typename Default >
850 struct map_find< std::tuple< pair< Key, Value >, Ts... >, Key, Default >
851 {
852 using type = Value;
853 };
854
855 template < typename Value, typename NotKey, typename Key, typename ...Ts, typename Default >
856 struct map_find< std::tuple< pair< NotKey, Value >, Ts... >, Key, Default >
857 {
858 using type = typename map_find< std::tuple< Ts... >, Key, Default >::type;
859 };
860
861 // Removes the key from the map
862 template < typename Map, typename Key >
863 struct map_erase;
864
865 template < typename Key >
866 struct map_erase< std::tuple<>, Key >
867 {
868 using type = std::tuple<>;
869 };
870
871 template < typename Key, typename Value, typename ...Ts >
872 struct map_erase< std::tuple< pair< Key, Value >, Ts... >, Key >
873 {
874 using type = std::tuple< Ts... >;
875 };
876
877 template < typename Key, typename NotKey, typename Value, typename ...Ts >
878 struct map_erase< std::tuple< pair< NotKey, Value >, Ts... >, Key >
879 {
880 using type = typename add_type<
881 pair< NotKey, Value >,
882 typename map_erase< std::tuple< Ts...>, Key >::type
883 >::type;
884 };
885
886 // inserts / replaces the Value under Key
887 template < typename Map, typename Key, typename Value >
888 struct map_insert
889 {
890 using type = typename add_type<
891 pair< Key, Value >,
892 typename map_erase< Map, Key >::type >::type;
893 };
894
895
896}
897}
898
899#endif
900
wrap< typename select_type_impl< Select >::template f< A, B > > select_type
Select A or B by Select. If Select == true, the result is A; B otherwise.
Definition: meta_tools.hpp:38
wrap< typename or_type_impl< Null, A >::template f< B > > or_type
return A if A is not Null, otherwise return B if B is not Null, otherwise Null
Definition: meta_tools.hpp:76