1 | #ifndef VECTOR_CREATOR |
2 | #define VECTOR_CREATOR |
3 | |
4 | #include <boost/fusion/container/vector.hpp> |
5 | #include <boost/mpl/vector.hpp> |
6 | #include <boost/mpl/push_back.hpp> |
7 | #include <boost/type_traits/remove_reference.hpp> |
8 | #include <boost/mpl/range_c.hpp> |
9 | #include <type_traits> |
10 | #include "util_debug.hpp" |
11 | #include "check_no_pointers.hpp" |
12 | #include "util/for_each_ref.hpp" |
13 | #include <iostream> |
14 | |
15 | /*! \brief functor for for_each algorithm |
16 | * |
17 | * It print a warnings for each properties that does not have noPointers method |
18 | * |
19 | * \tparam v original boost::fusion::vector with the properties |
20 | * |
21 | */ |
22 | template<typename v> |
23 | struct check_types |
24 | { |
25 | size_t & ret; |
26 | |
27 | check_types(size_t & ret) |
28 | :ret(ret) |
29 | { |
30 | ret = PNP::NO_POINTERS; |
31 | } |
32 | |
33 | template<typename T> |
34 | void operator()(T& t) |
35 | { |
36 | typedef typename std::remove_all_extents< typename boost::mpl::at<v,boost::mpl::int_<T::value> >::type>::type tpy; |
37 | |
38 | // if it is a pointer make no sense |
39 | if (std::is_pointer<tpy>::value == true) |
40 | {ret = PNP::POINTERS;return;} |
41 | |
42 | // if it is an l-value reference make no send |
43 | if (std::is_lvalue_reference<tpy>::value == true) |
44 | {ret = PNP::POINTERS;return;} |
45 | |
46 | // if it is an r-value reference make no send |
47 | if (std::is_rvalue_reference<tpy>::value == true) |
48 | {ret = PNP::POINTERS;return;} |
49 | |
50 | if (std::is_fundamental<tpy>::value == true) |
51 | {return;} |
52 | |
53 | // check that T has a method called noPointers |
54 | switch (check_no_pointers<tpy>::value()) |
55 | { |
56 | case PNP::UNKNOWN: |
57 | { |
58 | #ifndef DISABLE_ALL_RTTI |
59 | std::cerr << "Warning: " << __FILE__ << ":" << __LINE__ << " impossible to check the type " << demangle(typeid(tpy).name()) << " please consider to add a static method \"static bool noPointers()\" \n" ; |
60 | #endif |
61 | ret = PNP::UNKNOWN; |
62 | break; |
63 | } |
64 | case PNP::POINTERS: |
65 | { |
66 | ret = PNP::POINTERS; |
67 | break; |
68 | } |
69 | default: |
70 | { |
71 | |
72 | } |
73 | } |
74 | } |
75 | }; |
76 | |
77 | /*! \brief push p_ele into v only of to_push is true |
78 | * |
79 | * \tparam v vector where to push |
80 | * \tparam p_ele object to push |
81 | * \tparam to_push it push the element only if this flag is true |
82 | * |
83 | */ |
84 | template<typename v,typename p_ele,bool to_push> |
85 | struct conditional_push |
86 | { |
87 | typedef typename boost::mpl::push_front<v,p_ele>::type type; |
88 | }; |
89 | |
90 | /*! \brief push p_ele into v only of to_push is true |
91 | * |
92 | * \tparam v vector where to push |
93 | * \tparam p_ele object to push |
94 | * \tparam to_push it push the element only if this flag is true |
95 | * |
96 | */ |
97 | template<typename v,typename p_ele> |
98 | struct conditional_push<v,p_ele,false> |
99 | { |
100 | typedef v type; |
101 | }; |
102 | |
103 | /*! \brief Implementation of noPointer_sequence_impl |
104 | * |
105 | * Case of a property that has not noPointers method |
106 | * |
107 | * \tparam v original boost::fusion::vector |
108 | * \tparam p1 property we are considering |
109 | * \tparam remaining properties to push |
110 | * |
111 | */ |
112 | template<typename v, int p1, int... prp> |
113 | struct noPointers_sequence_impl |
114 | { |
115 | // Object we are analyzing |
116 | typedef typename std::remove_reference<typename std::remove_pointer<typename boost::mpl::at< v,boost::mpl::int_<p1> >::type>::type>::type obj_type; |
117 | |
118 | // analyze the other properties, returning the output vector |
119 | typedef typename noPointers_sequence_impl<v ,prp...>::type v_step; |
120 | |
121 | // push on the vector the element p1 |
122 | typedef typename conditional_push<v_step, boost::mpl::int_<p1>, !has_noPointers<obj_type>::value && !std::is_fundamental<obj_type>::value >::type type; |
123 | }; |
124 | |
125 | /*! \brief Implementation of noPointer_sequence_impl |
126 | * |
127 | * specialization for last properties |
128 | * |
129 | * \tparam v original boost::fusion::vector |
130 | * \tparam p1 property we are considering |
131 | * |
132 | */ |
133 | template<typename v, int p1> |
134 | struct noPointers_sequence_impl<v,p1> |
135 | { |
136 | // Object we are analyzing |
137 | typedef typename std::remove_reference< typename std::remove_pointer<typename boost::mpl::at< v,boost::mpl::int_<p1> >::type>::type>::type obj_type; |
138 | |
139 | // push on the vector the element p1 |
140 | typedef typename conditional_push<boost::mpl::vector<>, boost::mpl::int_<p1>, !has_noPointers<obj_type>::value && !std::is_fundamental<obj_type>::value >::type type; |
141 | }; |
142 | |
143 | /*! \brief it return a boost::mpl::vector of integers where each integer identify one object without the method "noPointers" |
144 | * |
145 | * ## Example |
146 | * |
147 | * \snippet util.hpp object creator check for no pointers |
148 | * |
149 | * \tparam v boost::fusion::vector |
150 | * \tparam prp selected properties |
151 | * |
152 | */ |
153 | template<typename v, int... prp> |
154 | struct noPointers_sequence |
155 | { |
156 | typedef typename noPointers_sequence_impl<v,prp...>::type type; |
157 | }; |
158 | |
159 | |
160 | /*! \brief This is a container to create a general object |
161 | * |
162 | * \note It is used in ghost_get to create a particular object with the properties selected |
163 | * |
164 | * For object we mean an object that follow the OpenFPM data structure format, see openFPM_data wiki |
165 | * for more information |
166 | * |
167 | * \tparam Is a boost::fusion::vector with the properties selected |
168 | * |
169 | * |
170 | */ |
171 | template<typename v> |
172 | struct object |
173 | { |
174 | typedef v type; |
175 | typedef typename boost::fusion::result_of::size<v>::type size_tpy; |
176 | |
177 | type data; |
178 | |
179 | static bool noPointers() |
180 | { |
181 | size_t ret; |
182 | check_types<v> ct(ret); |
183 | |
184 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0, boost::fusion::result_of::size<v>::type::value > > (ct); |
185 | |
186 | return ret; |
187 | } |
188 | |
189 | static const int max_prop = size_tpy::value; |
190 | }; |
191 | |
192 | /*! \brief Implementation of object creator |
193 | * |
194 | * \tparam v boost::fusion::vector |
195 | * \tparam vc basic boost::fusion::vector object from where start to push |
196 | * \tparam prp properties to push |
197 | * |
198 | */ |
199 | template<typename v, typename vc, int... prp> |
200 | struct object_creator_impl |
201 | { |
202 | }; |
203 | |
204 | /*! \brief Implementation of object creator |
205 | * |
206 | * \tparam v original boost::fusion::vector |
207 | * \tparam vc basic boost::fusion::vector object from where start to push |
208 | * \tparam p1 actual property |
209 | * \tparam remaining properties to push |
210 | * |
211 | */ |
212 | template<typename v, typename vc, int p1, int... prp> |
213 | struct object_creator_impl<v,vc,p1,prp...> |
214 | { |
215 | typedef typename object_creator_impl<v,vc,prp... >::type vc_step; |
216 | |
217 | typedef typename boost::remove_reference< typename boost::mpl::at< v,boost::mpl::int_<p1> >::type>::type ele; |
218 | |
219 | // push on the vector the element p1 |
220 | typedef typename boost::mpl::push_front<vc_step, ele >::type type; |
221 | }; |
222 | |
223 | /*! \brief Implementation of object creator |
224 | * |
225 | * \tparam v original boost::fusion::vector |
226 | * \tparam vc basic boost::fusion::vector object from where start to push |
227 | * \tparam prp property to push |
228 | */ |
229 | template<typename v, typename vc, int prp> |
230 | struct object_creator_impl<v,vc,prp> |
231 | { |
232 | typedef typename boost::remove_reference< typename boost::mpl::at< v,boost::mpl::int_<prp> >::type>::type ele; |
233 | |
234 | // push on the vector the element p1 |
235 | typedef typename boost::mpl::push_front<vc, ele >::type type; |
236 | }; |
237 | |
238 | /*! \brief It create a boost::fusion vector with the selected properties |
239 | * |
240 | * \tparam v boost::fusion::vector |
241 | * \tparam prp selected properties |
242 | * |
243 | * ## Create a compile-time object and copy *from* the selected properties |
244 | * \snippet util_test.hpp object copy example |
245 | * ## Create a compile-time Encap object and copy *from* the selected properties |
246 | * \snippet util_test.hpp object copy encap example |
247 | * ## Create a compile-time object and copy *to* the selected properties |
248 | * \snipper util_test.hpp object write example |
249 | * ## Create a compile-time Encap object and copy *to* the selected properties |
250 | * \snipper util_test.hpp object write encap example |
251 | * |
252 | * |
253 | */ |
254 | template<typename v, int... prp> |
255 | struct object_creator |
256 | { |
257 | typedef typename boost::fusion::result_of::as_vector<typename object_creator_impl<v,boost::mpl::vector<>,prp... >::type>::type type; |
258 | }; |
259 | |
260 | //! specialization when no properties are passed |
261 | template<typename v> |
262 | struct object_creator<v> |
263 | { |
264 | typedef v type; |
265 | }; |
266 | |
267 | ///////////////////////// Object creator for chunking data structure |
268 | |
269 | /*! \brief Implementation of object creator |
270 | * |
271 | * \tparam v boost::fusion::vector |
272 | * \tparam vc basic boost::fusion::vector object from where start to push |
273 | * \tparam prp properties to push |
274 | * |
275 | */ |
276 | template<typename v, typename vc, int... prp> |
277 | struct object_creator_chunking_impl |
278 | { |
279 | }; |
280 | |
281 | /*! \brief Implementation of object creator |
282 | * |
283 | * \tparam v original boost::fusion::vector |
284 | * \tparam vc basic boost::fusion::vector object from where start to push |
285 | * \tparam p1 actual property |
286 | * \tparam remaining properties to push |
287 | * |
288 | */ |
289 | template<typename v, typename vc, int p1, int... prp> |
290 | struct object_creator_chunking_impl<v,vc,p1,prp...> |
291 | { |
292 | typedef typename object_creator_chunking_impl<v,vc,prp... >::type vc_step; |
293 | |
294 | typedef typename boost::remove_reference< typename boost::mpl::at< v,boost::mpl::int_<p1> >::type>::type ele_array; |
295 | |
296 | // Element without array |
297 | typedef typename ele_array::value_type ele; |
298 | |
299 | // push on the vector the element p1 |
300 | typedef typename boost::mpl::push_front<vc_step, ele >::type type; |
301 | }; |
302 | |
303 | /*! \brief Implementation of object creator |
304 | * |
305 | * \tparam v original boost::fusion::vector |
306 | * \tparam vc basic boost::fusion::vector object from where start to push |
307 | * \tparam prp property to push |
308 | */ |
309 | template<typename v, typename vc, int prp> |
310 | struct object_creator_chunking_impl<v,vc,prp> |
311 | { |
312 | typedef typename boost::remove_reference< typename boost::mpl::at< v,boost::mpl::int_<prp> >::type>::type ele_array; |
313 | |
314 | // Element without array |
315 | typedef typename ele_array::value_type ele; |
316 | |
317 | // push on the vector the element p1 |
318 | typedef typename boost::mpl::push_front<vc, ele >::type type; |
319 | }; |
320 | |
321 | |
322 | template<typename v, int... prp> |
323 | struct object_creator_chunking |
324 | { |
325 | typedef typename boost::fusion::result_of::as_vector<typename object_creator_chunking_impl<v,boost::mpl::vector<>,prp... >::type>::type type; |
326 | }; |
327 | |
328 | |
329 | //! specialization when no properties are passed |
330 | template<typename v> |
331 | struct object_creator_chunking<v> |
332 | { |
333 | typedef v type; |
334 | }; |
335 | |
336 | #endif |
337 | |