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 */
22template<typename v>
23struct 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 */
84template<typename v,typename p_ele,bool to_push>
85struct 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 */
97template<typename v,typename p_ele>
98struct 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 */
112template<typename v, int p1, int... prp>
113struct 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 */
133template<typename v, int p1>
134struct 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 */
153template<typename v, int... prp>
154struct 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 */
171template<typename v>
172struct 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 */
199template<typename v, typename vc, int... prp>
200struct 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 */
212template<typename v, typename vc, int p1, int... prp>
213struct 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 */
229template<typename v, typename vc, int prp>
230struct 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 */
254template<typename v, int... prp>
255struct 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
261template<typename v>
262struct 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 */
276template<typename v, typename vc, int... prp>
277struct 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 */
289template<typename v, typename vc, int p1, int... prp>
290struct 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 */
309template<typename v, typename vc, int prp>
310struct 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
322template<typename v, int... prp>
323struct 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
330template<typename v>
331struct object_creator_chunking<v>
332{
333 typedef v type;
334};
335
336#endif
337