CANdevStudio
Development tool for CAN bus simulation
Loading...
Searching...
No Matches
visitor.h
Go to the documentation of this file.
1
2#ifndef VISTOR_H
3#define VISTOR_H
4
5#include <functional> // function
6#include <tuple> // tuple, tuple_element, get
7#include <type_traits> // {is,remove}_reference, {true,false}_type, enable_if
8#include <utility> // move, forward
9
10#include "visitablewith.h" // VisitableWith
11
12
13
39template<class Tag, class... Visitables>
41{
42
43 public:
44
45 using visitable_types = std::tuple<Visitables...>; // DO NOT PASS REFERENCES
46
47 private:
48
49 template<class... T>
50 struct are_bare_types
51 : std::true_type
52 {};
53
54 template<class T, class... Ts>
55 struct are_bare_types<std::tuple<T, Ts...>>
56 {
57 static const bool value =
58 ! std::is_reference<T>::value
59 && are_bare_types<Ts...>::value;
60 };
61
62 template<class T>
63 struct are_bare_types<std::tuple<T>>
64 {
65 static const bool value =
66 ! std::is_reference<T>::value;
67 };
68
69
70 template<class T, class U>
71 struct is_within
72 : std::false_type
73 {};
74
75 template<class T, class... Ts>
76 struct is_within<T, std::tuple<T, Ts...>>
77 : std::true_type
78 {};
79
80 template<class T, class U, class... Ts>
81 struct is_within<T, std::tuple<U, Ts...>>
82 : is_within<T, std::tuple<Ts...>>
83 {};
84
85
86 template<class F>
87 struct action_traits
88 : action_traits<decltype(&std::remove_reference_t<F>::operator())>
89 {};
90
91 template<class R, class T, class... As> // mutable lambda
92 struct action_traits<R (T::*)(As...)>
93 : action_traits<R (T::*)(As...) const>
94 {};
95
96 template<class R, class T, class... As>
97 struct action_traits<R (T::*)(As...) const>
98 {
99 static constexpr auto arity = sizeof...(As);
100
101 using result_type = R;
102
103 template<unsigned I>
104 using arg_type = std::tuple_element_t<I, std::tuple<As...>>;
105 };
106
107
108 template<class F>
109 using arg0_type = typename action_traits<F>::template arg_type<0>;
110
111
112 template<class T, class F, class... Fs>
113 struct are_actions_allowed
114 {
115 static const bool value =
116 is_within<std::remove_reference_t<arg0_type<F>>, T>::value
117 && are_actions_allowed<T, Fs...>::value;
118 };
119
120 template<class T, class F>
121 struct are_actions_allowed<T, F>
122 {
123 static const bool value =
124 is_within<std::remove_reference_t<arg0_type<F>>, T>::value;
125 };
126
127
128 public:
129
130 static_assert(are_bare_types<visitable_types>::value
131 , "Visitable types cannot be references");
132
133
134 template<class T>
135 auto operator()(T& t)
136 -> std::enable_if_t<is_within<T, visitable_types>::value, void>
137 {
138 if (std::get<action_type<T>>(actions)) // action specified?
139 {
140 std::get<action_type<T>>(actions)(t);
141 }
143 }
144
145
146 template<class... Fs>
147 Visitor(Fs&&... fs)
148 {
149 static_assert(are_actions_allowed<visitable_types, Fs...>::value
150 , "Unexpected action passed");
151
152 fill_in(actions, std::forward<Fs>(fs)...);
153 }
154
155
156 private:
157
158 void operator()(...) = delete; // passed type is not in visitable types!
159
160
161 template<class T, class F>
162 static void assign_action(T&& t, F&& f)
163 {
164 std::get<action_type<arg0_type<F>>>(std::forward<T>(t)) = std::forward<F>(f);
165 }
166
167 template<class T, class... Fs>
168 static void fill_in(T&& t, Fs&&... fs)
169 {
170 int dummy[sizeof...(Fs)] =
171 { (assign_action(std::forward<T>(t), std::forward<Fs>(fs)), 0)... };
172
173 (void) dummy;
174 }
175
176
177 template<class T>
178 using action_type = std::function<void (T&)>;
179
180 template<class Ts>
181 struct make_action_types;
182
183 template<class... Ts>
184 struct make_action_types<std::tuple<Ts...>>
185 {
186 using type = std::tuple<action_type<Ts>...>;
187 };
188
189
190 using action_types = typename make_action_types<visitable_types>::type;
191
192 action_types actions;
193};
194
195#endif
196
Definition visitor.h:41
auto operator()(T &t) -> std::enable_if_t< is_within< T, visitable_types >::value, void >
Definition visitor.h:135
std::tuple< Visitables... > visitable_types
Definition visitor.h:45
Visitor(Fs &&... fs)
Definition visitor.h:147