1 | /* |
2 | * to_variadic.hpp |
3 | * |
4 | * Set of classes to convert from a boost::mpl::vector into an S variadic template |
5 | * class appling a metafunction F on each element |
6 | * |
7 | * boost::mpl::vector<T,A,B> is converted into |
8 | * |
9 | * S<F<T>,F<A>,F<B>> |
10 | * |
11 | * \see to_variadic |
12 | * |
13 | * Created on: Aug 27, 2014 |
14 | * Author: Pietro Incardona |
15 | */ |
16 | |
17 | #ifndef V_TRANSFORM_HPP |
18 | #define V_TRANSFORM_HPP |
19 | |
20 | #include <boost/fusion/container/vector.hpp> |
21 | #include <boost/mpl/int.hpp> |
22 | #include <boost/mpl/reverse.hpp> |
23 | #include <boost/mpl/vector.hpp> |
24 | #include <boost/mpl/range_c.hpp> |
25 | #include <boost/fusion/sequence/intrinsic/at_c.hpp> |
26 | #include <boost/fusion/include/at_c.hpp> |
27 | #include <boost/mpl/accumulate.hpp> |
28 | |
29 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
30 | |
31 | /*! \brief Exit condition |
32 | * |
33 | * Exit condition, when the distance between F and L is 0 return true |
34 | * |
35 | * \param F suppose to be the end of the mpl::vector |
36 | * \param L suppose to be the actual position of the mpl::vector |
37 | * |
38 | */ |
39 | |
40 | template<typename F,typename L> |
41 | struct exit_impl : boost::mpl::equal_to<typename boost::mpl::distance<F,L>::type,boost::mpl::int_<0>> |
42 | {}; |
43 | |
44 | /*! \brief Recursive specialization of v_transform |
45 | * |
46 | * \param F suppose to be the original end of boost::mpl::vector |
47 | * \param L suppose to be the actual position of the boost::mpl::vector |
48 | * \param exit, when true it say to terminate the sequence |
49 | * |
50 | */ |
51 | template<template<typename> class H, typename F,typename L, bool exit,typename ...Args> |
52 | struct v_transform_impl |
53 | { |
54 | //! last element of the vector |
55 | typedef typename boost::mpl::deref<F>::type front_; |
56 | |
57 | //! next element |
58 | typedef typename boost::mpl::next<F>::type next_; |
59 | |
60 | //! exit condition |
61 | typedef typename exit_impl<next_,L>::type exit_; |
62 | |
63 | //! recursive call |
64 | typedef typename v_transform_impl<H,next_,L,exit_::value,typename H<front_>::type,Args...>::type type; |
65 | }; |
66 | |
67 | |
68 | //! Terminator of to_variadic |
69 | template<template<typename> class H,typename F,typename L,typename ...Args> |
70 | struct v_transform_impl<H,F,L,true,Args...> |
71 | { |
72 | //! required transformed type |
73 | typedef boost::fusion::vector<Args...> type; |
74 | }; |
75 | |
76 | //! implementation of seq_traits |
77 | template<typename Seq> |
78 | struct seq_traits_impl |
79 | { |
80 | //! first element |
81 | typedef typename boost::mpl::begin<Seq>::type first_; |
82 | |
83 | //! Last element |
84 | typedef typename boost::mpl::end<Seq>::type last_; |
85 | |
86 | //! exit condition (first == last) |
87 | typedef typename exit_impl<first_,last_>::type exit_; |
88 | }; |
89 | |
90 | /*! |
91 | * |
92 | * It transform a boost::fusion::vector to another boost::fusion::vector |
93 | * applying a meta-function H on each element |
94 | * |
95 | * \param H metafunction (is a structure with typedef type) |
96 | * \param L boost::fusion::vector |
97 | * |
98 | * ### Meta-function definition |
99 | * \snippet variadic_to_vmpl_unit_test.hpp v_transform metafunction |
100 | * |
101 | * ### Usage |
102 | * \snippet variadic_to_vmpl_unit_test.hpp v_transform usage |
103 | * |
104 | */ |
105 | |
106 | template<template<typename> class H,typename L> |
107 | struct v_transform |
108 | { |
109 | //! reverse the sequence |
110 | typedef typename boost::mpl::reverse<L>::type reversed_; |
111 | |
112 | //! first element |
113 | typedef typename seq_traits_impl<reversed_>::first_ first; |
114 | |
115 | //! last element |
116 | typedef typename seq_traits_impl<reversed_>::last_ last; |
117 | |
118 | //! calculate the exit condition |
119 | typedef typename exit_impl<first,last>::type exit_; |
120 | |
121 | //! generate the boost::fusion::vector apply H on each term |
122 | typedef typename v_transform_impl<H,first,last,exit_::value >::type type; |
123 | }; |
124 | |
125 | |
126 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// |
127 | |
128 | |
129 | /*! \brief Recursive specialization of v_transform in case of metafunction with 2 argument |
130 | * |
131 | * \param H the metafunction |
132 | * \param F suppose to be the original end of boost::mpl::vector |
133 | * \param L suppose to be the actual position of the boost::mpl::vector |
134 | * \param exit, when true it say to terminate the sequence |
135 | * |
136 | */ |
137 | template<template<typename,typename> class H, typename arg0, typename F,typename L, bool exit,typename ...Args> |
138 | struct v_transform_two_impl |
139 | { |
140 | //! last element of the vector |
141 | typedef typename boost::mpl::deref<F>::type front_; |
142 | |
143 | //! next element of the vector |
144 | typedef typename boost::mpl::next<F>::type next_; |
145 | |
146 | //! exit condition |
147 | typedef typename exit_impl<next_,L>::type exit_; |
148 | |
149 | //! Recursive call |
150 | typedef typename v_transform_two_impl<H,arg0,next_,L,exit_::value,typename H<arg0,front_>::type,Args...>::type type; |
151 | }; |
152 | |
153 | //! Terminator of to_variadic |
154 | template<template<typename,typename> class H,typename arg0, typename F,typename L,typename ...Args> |
155 | struct v_transform_two_impl<H,arg0,F,L,true,Args...> |
156 | { |
157 | //! Required type |
158 | typedef boost::fusion::vector<Args...> type; |
159 | }; |
160 | |
161 | /*! |
162 | * |
163 | * It transform a boost::fusion::vector to another boost::fusion::vector |
164 | * applying a meta-function H on each element |
165 | * |
166 | * \param H 2-argument metafunction (is a structure with typedef type) |
167 | * \param L boost::fusion::vector |
168 | * |
169 | * ### Meta-function definition |
170 | * \snippet variadic_to_vmpl_unit_test.hpp v_transform_two metafunction |
171 | * |
172 | * ### Usage |
173 | * \snippet variadic_to_vmpl_unit_test.hpp v_transform_two usage |
174 | * |
175 | */ |
176 | |
177 | template<template<typename,typename> class H,typename arg0, typename L> |
178 | struct v_transform_two |
179 | { |
180 | //! reverse the sequence |
181 | typedef typename boost::mpl::reverse<L>::type reversed_; |
182 | |
183 | //! first element |
184 | typedef typename seq_traits_impl<reversed_>::first_ first; |
185 | |
186 | //! last element |
187 | typedef typename seq_traits_impl<reversed_>::last_ last; |
188 | |
189 | //! calculate the exit condition |
190 | typedef typename exit_impl<first,last>::type exit_; |
191 | |
192 | //! generate the boost::fusion::vector apply H on each term |
193 | typedef typename v_transform_two_impl<H,arg0,first,last,exit_::value >::type type; |
194 | }; |
195 | |
196 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// |
197 | |
198 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// |
199 | |
200 | |
201 | /*! \brief Recursive specialization of v_transform in case of metafunction with 2 argument |
202 | * |
203 | * \param H the metafunction |
204 | * \param F suppose to be the original end of boost::mpl::vector |
205 | * \param L suppose to be the actual position of the boost::mpl::vector |
206 | * \param exit, when true it say to terminate the sequence |
207 | * |
208 | */ |
209 | template<template<typename,typename> class H, typename arg0, typename F,typename L, bool exit,typename ...Args> |
210 | struct v_transform_two_v2_impl |
211 | { |
212 | //! last element of the vector |
213 | typedef typename boost::mpl::deref<F>::type front_; |
214 | |
215 | //! next element of the vector |
216 | typedef typename boost::mpl::next<F>::type next_; |
217 | |
218 | //! exit condition |
219 | typedef typename exit_impl<next_,L>::type exit_; |
220 | |
221 | //! Recursive call |
222 | typedef typename v_transform_two_v2_impl<H,arg0,next_,L,exit_::value,typename H<arg0,front_>::type::type,Args...>::type type; |
223 | }; |
224 | |
225 | //! Terminator of to_variadic |
226 | template<template<typename,typename> class H,typename arg0, typename F,typename L,typename ...Args> |
227 | struct v_transform_two_v2_impl<H,arg0,F,L,true,Args...> |
228 | { |
229 | //! Required type |
230 | typedef boost::fusion::vector<Args...> type; |
231 | }; |
232 | |
233 | /*! |
234 | * |
235 | * It transform a boost::fusion::vector to another boost::fusion::vector |
236 | * applying a meta-function H on each element |
237 | * |
238 | * \param H 2-argument metafunction (is a structure with typedef type) |
239 | * \param L boost::fusion::vector |
240 | * |
241 | * ### Meta-function definition |
242 | * \snippet variadic_to_vmpl_unit_test.hpp v_transform_two metafunction |
243 | * |
244 | * ### Usage |
245 | * \snippet variadic_to_vmpl_unit_test.hpp v_transform_two usage |
246 | * |
247 | */ |
248 | |
249 | template<template<typename,typename> class H,typename arg0, typename L> |
250 | struct v_transform_two_v2 |
251 | { |
252 | //! reverse the sequence |
253 | typedef typename boost::mpl::reverse<L>::type reversed_; |
254 | |
255 | //! first element |
256 | typedef typename seq_traits_impl<reversed_>::first_ first; |
257 | |
258 | //! last element |
259 | typedef typename seq_traits_impl<reversed_>::last_ last; |
260 | |
261 | //! calculate the exit condition |
262 | typedef typename exit_impl<first,last>::type exit_; |
263 | |
264 | //! generate the boost::fusion::vector apply H on each term |
265 | typedef typename v_transform_two_v2_impl<H,arg0,first,last,exit_::value >::type type; |
266 | }; |
267 | |
268 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// |
269 | |
270 | /*! |
271 | * |
272 | * It convert a variadic template into a boost::mpl::vector |
273 | * |
274 | * to_boost_vmpl<3,4,7,10>::type is converted into |
275 | * |
276 | * boost::mpl::vector<int_<3>,int_<4>,int_<7>,int_<10>> |
277 | * |
278 | * \snippet variadic_to_vmpl_unit_test.hpp to_boost_vmpl usage |
279 | * |
280 | */ |
281 | template <int... id> |
282 | struct to_boost_vmpl |
283 | { |
284 | //! construct an mpl vector from the variadic |
285 | typedef boost::mpl::vector<boost::mpl::int_<id>...> type; |
286 | }; |
287 | |
288 | ///////////////////// Meta-code to restrieve first and last of variadic template |
289 | |
290 | template <unsigned T1, unsigned int ...T> |
291 | struct first_variadic |
292 | { |
293 | typedef boost::mpl::int_<T1> type; |
294 | }; |
295 | |
296 | template <unsigned int T1, unsigned int ...T> |
297 | struct last_variadic |
298 | { |
299 | typedef typename last_variadic<T...>::type type; |
300 | }; |
301 | |
302 | template <unsigned int T1> |
303 | struct last_variadic<T1> |
304 | { |
305 | typedef boost::mpl::int_<T1> type; |
306 | }; |
307 | |
308 | template <unsigned int ... prp> |
309 | struct is_contiguos |
310 | { |
311 | typedef boost::mpl::range_c<int,first_variadic<prp...>::type::value,last_variadic<prp...>::type::value + 1> rangec; |
312 | |
313 | typedef typename boost::mpl::size<rangec>::type size_range; |
314 | |
315 | typedef typename boost::mpl::accumulate<rangec, |
316 | boost::mpl::int_<0>, |
317 | boost::mpl::plus<typename boost::mpl::placeholders::_2, |
318 | typename boost::mpl::placeholders::_1> |
319 | >::type accum; |
320 | |
321 | typedef typename to_boost_vmpl<prp...>::type prop_vector; |
322 | |
323 | typedef typename boost::mpl::accumulate<prop_vector, |
324 | boost::mpl::int_<0>, |
325 | boost::mpl::plus<typename boost::mpl::placeholders::_2, |
326 | typename boost::mpl::placeholders::_1> |
327 | >::type accum_prp; |
328 | |
329 | typedef boost::mpl::bool_<sizeof...(prp) == size_range::value && accum_prp::value == accum::value > type; |
330 | }; |
331 | |
332 | #endif |
333 | |