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
40template<typename F,typename L>
41struct 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 */
51template<template<typename> class H, typename F,typename L, bool exit,typename ...Args>
52struct 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
69template<template<typename> class H,typename F,typename L,typename ...Args>
70struct 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
77template<typename Seq>
78struct 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
106template<template<typename> class H,typename L>
107struct 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 */
137template<template<typename,typename> class H, typename arg0, typename F,typename L, bool exit,typename ...Args>
138struct 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
154template<template<typename,typename> class H,typename arg0, typename F,typename L,typename ...Args>
155struct 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
177template<template<typename,typename> class H,typename arg0, typename L>
178struct 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 */
209template<template<typename,typename> class H, typename arg0, typename F,typename L, bool exit,typename ...Args>
210struct 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
226template<template<typename,typename> class H,typename arg0, typename F,typename L,typename ...Args>
227struct 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
249template<template<typename,typename> class H,typename arg0, typename L>
250struct 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*/
281template <int... id>
282struct 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
290template <unsigned T1, unsigned int ...T>
291struct first_variadic
292{
293 typedef boost::mpl::int_<T1> type;
294};
295
296template <unsigned int T1, unsigned int ...T>
297struct last_variadic
298{
299 typedef typename last_variadic<T...>::type type;
300};
301
302template <unsigned int T1>
303struct last_variadic<T1>
304{
305 typedef boost::mpl::int_<T1> type;
306};
307
308template <unsigned int ... prp>
309struct 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