1 | 29,226d28
|
---|
2 | <
|
---|
3 | < //this should probably go to boost/tuple/tuple.hpp
|
---|
4 | < namespace boost { namespace tuples{
|
---|
5 | <
|
---|
6 | < template<int I, class...Args>
|
---|
7 | < struct element<I, std::tuple<Args...> > {
|
---|
8 | < typedef typename std::tuple_element<I, std::tuple<Args...> >::type type;
|
---|
9 | < };
|
---|
10 | <
|
---|
11 | < template<class T1, class T2>
|
---|
12 | < struct element<0, std::pair<T1, T2> > {
|
---|
13 | < typedef T1 type;
|
---|
14 | < };
|
---|
15 | <
|
---|
16 | < template<class T1, class T2>
|
---|
17 | < struct element<1, std::pair<T1, T2> > {
|
---|
18 | < typedef T2 type;
|
---|
19 | < };
|
---|
20 | < }}
|
---|
21 | <
|
---|
22 | <
|
---|
23 | < //helper classes to work with std::tuple
|
---|
24 | < namespace helper {
|
---|
25 | <
|
---|
26 | < //get head of std::tuple
|
---|
27 | < template<class T> struct head{
|
---|
28 | < typedef decltype( std::get<0>( std::declval<T>() ) ) type;
|
---|
29 | < };
|
---|
30 | <
|
---|
31 | < //get tail of std::tuple
|
---|
32 | < template<class T> struct tail{ typedef std::tuple<> type; };
|
---|
33 | <
|
---|
34 | < //specialisations allow for perfect forwarding
|
---|
35 | < template<class T, class... Args>
|
---|
36 | < struct tail< std::tuple<T, Args...>& >{
|
---|
37 | <
|
---|
38 | < typedef typename std::conditional<
|
---|
39 | < sizeof...(Args) == 0,
|
---|
40 | < std::tuple<>,
|
---|
41 | < std::tuple<Args...>&
|
---|
42 | < >::type type;
|
---|
43 | < };
|
---|
44 | <
|
---|
45 | < template<class T, class... Args>
|
---|
46 | < struct tail< std::tuple<T, Args...> const& >{
|
---|
47 | < typedef typename std::conditional<
|
---|
48 | < sizeof...(Args) == 0,
|
---|
49 | < std::tuple<>,
|
---|
50 | < std::tuple<Args...> const&
|
---|
51 | < >::type type;
|
---|
52 | < };
|
---|
53 | <
|
---|
54 | < template<class T, class... Args>
|
---|
55 | < struct tail< std::tuple<T, Args...>&& >{
|
---|
56 | < typedef typename std::conditional<
|
---|
57 | < sizeof...(Args) == 0,
|
---|
58 | < std::tuple<>,
|
---|
59 | < std::tuple<Args...> &&
|
---|
60 | < >::type type;
|
---|
61 | < };
|
---|
62 | <
|
---|
63 | <
|
---|
64 | < //concatenate 2 tuples
|
---|
65 | < template<class Tuple1, class Tuple2> struct concat {
|
---|
66 | <
|
---|
67 | < typedef decltype( std::tuple_cat(std::declval<Tuple1>(),
|
---|
68 | < std::declval<Tuple2>()) ) type;
|
---|
69 | <
|
---|
70 | < inline static type call(Tuple1&& t1, Tuple2&& t2) {
|
---|
71 | < return std::tuple_cat( std::forward<Tuple1>(t1),
|
---|
72 | < std::forward<Tuple2>(t2) );
|
---|
73 | < }
|
---|
74 | < };
|
---|
75 | <
|
---|
76 | <
|
---|
77 | < //wrap mpl meta function to allow return type derivation via decltype
|
---|
78 | < template<class F>
|
---|
79 | < struct wrap {
|
---|
80 | < typedef typename boost::mpl::lambda<F>::type Lambda;
|
---|
81 | <
|
---|
82 | <
|
---|
83 | < template<class... Args>
|
---|
84 | < struct result {
|
---|
85 | < typedef typename Lambda::template apply<Args...>::type type;
|
---|
86 | < };
|
---|
87 | <
|
---|
88 | < template<class... Args>
|
---|
89 | < typename result<Args...>::type operator()(Args...)
|
---|
90 | < {
|
---|
91 | < return std::declval< typename result<Args...>::type >();
|
---|
92 | < }
|
---|
93 | < };
|
---|
94 | <
|
---|
95 | <
|
---|
96 | <
|
---|
97 | < // Apply unary functor to each member of tuple
|
---|
98 | < template<class F,
|
---|
99 | < class Tuple,
|
---|
100 | < class Output= std::tuple<> >
|
---|
101 | < struct apply
|
---|
102 | < {
|
---|
103 | < typedef typename std::result_of<F(typename head<Tuple>::type)>::type
|
---|
104 | < result_type;
|
---|
105 | <
|
---|
106 | < typedef apply< F,
|
---|
107 | < typename tail<Tuple>::type,
|
---|
108 | < typename concat<Output,
|
---|
109 | < std::tuple<result_type> >::type > next;
|
---|
110 | <
|
---|
111 | < typedef typename next::type type;
|
---|
112 | <
|
---|
113 | <
|
---|
114 | < //function to implemnt the apply functionality
|
---|
115 | < template<int I=0, class T>
|
---|
116 | < static typename apply<F, Tuple>::type
|
---|
117 | < call(F f, T&& in)
|
---|
118 | < {
|
---|
119 | < return concat <
|
---|
120 | < std::tuple<result_type>,
|
---|
121 | < typename apply<
|
---|
122 | < F,
|
---|
123 | < typename tail<Tuple>::type
|
---|
124 | < >::type
|
---|
125 | < >::call( std::tuple<result_type>( f( std::get<I>( std::forward<T>(in) ))),
|
---|
126 | < next::template call<I+1>(f, std::forward<T>(in) ) );
|
---|
127 | < }
|
---|
128 | < };
|
---|
129 | <
|
---|
130 | < //Specialisation for empty tuples
|
---|
131 | < template<class F, class Output>
|
---|
132 | < struct apply< F, std::tuple<>, Output>
|
---|
133 | < {
|
---|
134 | < typedef Output type;
|
---|
135 | <
|
---|
136 | < template<int I=0, class T>
|
---|
137 | < inline static typename std::tuple<> call(F, T) { return std::tuple<>(); }
|
---|
138 | < };
|
---|
139 | <
|
---|
140 | < //Successively apply binary operator to tuple members
|
---|
141 | < template<class Tuple,
|
---|
142 | < class Op,
|
---|
143 | < class State >
|
---|
144 | < struct accumulate
|
---|
145 | < {
|
---|
146 | < typedef typename std::result_of<Op(typename head<Tuple>::type,
|
---|
147 | < State)>::type result_type;
|
---|
148 | <
|
---|
149 | <
|
---|
150 | < typedef accumulate< typename tail<Tuple>::type,
|
---|
151 | < Op,
|
---|
152 | < result_type > next;
|
---|
153 | <
|
---|
154 | < typedef typename next::type type;
|
---|
155 | <
|
---|
156 | < template<int I=0, class T>
|
---|
157 | < static type call(T&& in, Op op, State state)
|
---|
158 | < {
|
---|
159 | < return next::template call<I+1>(std::forward<T>(in),
|
---|
160 | < op,
|
---|
161 | < op( std::get<I>(std::forward<T>(in)),
|
---|
162 | < state ) );
|
---|
163 | < }
|
---|
164 | < };//accumulate
|
---|
165 | <
|
---|
166 | < //Specialisation for empty tuple
|
---|
167 | < template<class Op,
|
---|
168 | < class State >
|
---|
169 | < struct accumulate< std::tuple<>, Op, State>
|
---|
170 | < {
|
---|
171 | < typedef State type;
|
---|
172 | <
|
---|
173 | < template<int I=0, class T>
|
---|
174 | < static type call(T, Op, State state) { return state; }
|
---|
175 | < };
|
---|
176 | <
|
---|
177 | <
|
---|
178 | < //for each specialisation for std::tuples
|
---|
179 | < template<size_t I = 0, typename F, typename Tuple>
|
---|
180 | < inline typename std::enable_if< I == std::tuple_size<Tuple>::value, F>::type
|
---|
181 | < for_each(Tuple&, F f){ return f; }
|
---|
182 | <
|
---|
183 | < template<size_t I = 0, typename F, typename Tuple>
|
---|
184 | < inline typename std::enable_if< I != std::tuple_size<Tuple>::value, F>::type
|
---|
185 | < for_each(Tuple& t, F f)
|
---|
186 | < {
|
---|
187 | < f( std::get<I>(t) );
|
---|
188 | < return for_each<I+1>(t, f);
|
---|
189 | < }
|
---|
190 | <
|
---|
191 | <
|
---|
192 | <
|
---|
193 | < }//namespace helper
|
---|
194 | <
|
---|
195 | <
|
---|
196 | <
|
---|
197 | <
|
---|
198 | <
|
---|
199 | <
|
---|
200 | 334,357d135
|
---|
201 | <
|
---|
202 | < // Specialisation for std::tuple
|
---|
203 | < template<class... Args, class UnaryMetaFun>
|
---|
204 | < struct tuple_meta_transform< std::tuple<Args...>, UnaryMetaFun>
|
---|
205 | < {
|
---|
206 | < typedef typename helper::apply< helper::wrap<UnaryMetaFun>,
|
---|
207 | < std::tuple<Args...> const& >::type type;
|
---|
208 | < };
|
---|
209 | <
|
---|
210 | < // Specialisation for std::pair
|
---|
211 | < template<class T1, class T2, class UnaryMetaFun>
|
---|
212 | < struct tuple_meta_transform< std::pair<T1, T2>, UnaryMetaFun>
|
---|
213 | < {
|
---|
214 | < typedef std::pair<
|
---|
215 | < typename mpl::apply1<
|
---|
216 | < typename mpl::lambda<UnaryMetaFun>::type
|
---|
217 | < , T1
|
---|
218 | < >::type
|
---|
219 | < , typename mpl::apply1<
|
---|
220 | < typename mpl::lambda<UnaryMetaFun>::type
|
---|
221 | < , T2
|
---|
222 | < >::type
|
---|
223 | < > type;
|
---|
224 | < };
|
---|
225 | 409,444d186
|
---|
226 | < // specialisation for std::tuples
|
---|
227 | < template<class... Args, class BinaryMetaFun, typename StartType>
|
---|
228 | < struct tuple_meta_accumulate< std::tuple<Args...>,
|
---|
229 | < BinaryMetaFun,
|
---|
230 | < StartType >
|
---|
231 | < {
|
---|
232 | < typedef typename helper::accumulate<
|
---|
233 | < std::tuple<Args...>,
|
---|
234 | < helper::wrap<BinaryMetaFun>,
|
---|
235 | < StartType
|
---|
236 | < >::type type;
|
---|
237 | < };
|
---|
238 | <
|
---|
239 | < // specialisation for std::pair
|
---|
240 | < template<
|
---|
241 | < typename T1
|
---|
242 | < , typename T2
|
---|
243 | < , class BinaryMetaFun
|
---|
244 | < , typename StartType
|
---|
245 | < >
|
---|
246 | < struct tuple_meta_accumulate < std::pair<T1, T2>,
|
---|
247 | < BinaryMetaFun,
|
---|
248 | < StartType >
|
---|
249 | < {
|
---|
250 | < typedef typename mpl::apply2<
|
---|
251 | < typename mpl::lambda<BinaryMetaFun>::type,
|
---|
252 | < StartType,
|
---|
253 | < typename mpl::apply2<
|
---|
254 | < typename mpl::lambda<BinaryMetaFun>::type,
|
---|
255 | < T1,
|
---|
256 | < T2
|
---|
257 | < >::type
|
---|
258 | < >::type type;
|
---|
259 | < };
|
---|
260 | <
|
---|
261 | <
|
---|
262 | 478,479c220,224
|
---|
263 | < namespace detail{
|
---|
264 | <
|
---|
265 | ---
|
---|
266 | > template<typename Fun>
|
---|
267 | > tuples::null_type BOOST_TUPLE_ALGO(tuple_transform)
|
---|
268 | > (tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR)
|
---|
269 | > { return tuples::null_type(); }
|
---|
270 | >
|
---|
271 | 481,485c226,236
|
---|
272 | < struct tuple_transform_impl {
|
---|
273 | <
|
---|
274 | < static typename tuple_meta_transform<Tuple, Fun>::type
|
---|
275 | < BOOST_TUPLE_ALGO(call)(const Tuple& t, Fun f BOOST_TUPLE_ALGO_RECURSE )
|
---|
276 | < {
|
---|
277 | ---
|
---|
278 | > typename tuple_meta_transform<
|
---|
279 | > Tuple
|
---|
280 | > , Fun
|
---|
281 | > >::type
|
---|
282 | >
|
---|
283 | > BOOST_TUPLE_ALGO(tuple_transform)(
|
---|
284 | > const Tuple& t,
|
---|
285 | > Fun f
|
---|
286 | > BOOST_TUPLE_ALGO_RECURSE
|
---|
287 | > )
|
---|
288 | > {
|
---|
289 | 490,501c241,250
|
---|
290 | <
|
---|
291 | < return tuples::cons<
|
---|
292 | < BOOST_DEDUCED_TYPENAME mpl::apply1<
|
---|
293 | < Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type
|
---|
294 | < >::type
|
---|
295 | < , transformed_tail_type
|
---|
296 | < >(
|
---|
297 | < f(boost::tuples::get<0>(t)),
|
---|
298 | < tuple_transform_impl<BOOST_DEDUCED_TYPENAME Tuple::tail_type,
|
---|
299 | < Fun>::call( t.get_tail(), f)
|
---|
300 | < );
|
---|
301 | < }
|
---|
302 | ---
|
---|
303 | >
|
---|
304 | > return tuples::cons<
|
---|
305 | > BOOST_DEDUCED_TYPENAME mpl::apply1<
|
---|
306 | > Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type
|
---|
307 | > >::type
|
---|
308 | > , transformed_tail_type
|
---|
309 | > >(
|
---|
310 | > f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f)
|
---|
311 | > );
|
---|
312 | > }
|
---|
313 | 504,508c253,265
|
---|
314 | < static typename tuple_meta_transform<Tuple, Fun>::type
|
---|
315 | < call(const Tuple& t, Fun f)
|
---|
316 | < {
|
---|
317 | < return call_impl(t, f, 1);
|
---|
318 | < }
|
---|
319 | ---
|
---|
320 | > template<typename Tuple, typename Fun>
|
---|
321 | > typename tuple_meta_transform<
|
---|
322 | > Tuple
|
---|
323 | > , Fun
|
---|
324 | > >::type
|
---|
325 | >
|
---|
326 | > tuple_transform(
|
---|
327 | > const Tuple& t,
|
---|
328 | > Fun f
|
---|
329 | > )
|
---|
330 | > {
|
---|
331 | > return tuple_transform_impl(t, f, 1);
|
---|
332 | > }
|
---|
333 | 510,551d266
|
---|
334 | < };//tuple_transform_impl
|
---|
335 | <
|
---|
336 | <
|
---|
337 | < template<typename Fun>
|
---|
338 | < struct tuple_transform_impl<tuples::null_type, Fun> {
|
---|
339 | <
|
---|
340 | < static tuples::null_type
|
---|
341 | < BOOST_TUPLE_ALGO(call)(tuples::null_type const&,
|
---|
342 | < Fun BOOST_TUPLE_ALGO_TERMINATOR)
|
---|
343 | < {
|
---|
344 | < return tuples::null_type();
|
---|
345 | < }
|
---|
346 | < };
|
---|
347 | <
|
---|
348 | <
|
---|
349 | < // specialisation for std::tuples
|
---|
350 | < template<typename...Args, typename Fun>
|
---|
351 | < struct tuple_transform_impl <std::tuple<Args...>, Fun> {
|
---|
352 | <
|
---|
353 | < template<class T>
|
---|
354 | < inline static
|
---|
355 | < typename tuple_meta_transform< std::tuple<Args...>, Fun>::type
|
---|
356 | < call(T&& t, Fun f )
|
---|
357 | < {
|
---|
358 | < return helper::apply<Fun, T&&>::template call<0>(f, std::forward<T>(t) );
|
---|
359 | < }
|
---|
360 | < };
|
---|
361 | <
|
---|
362 | < //specialisation for std::pair
|
---|
363 | < template<typename T1, typename T2, typename Fun>
|
---|
364 | < struct tuple_transform_impl< std::pair<T1, T2>, Fun> {
|
---|
365 | <
|
---|
366 | < static typename tuple_meta_transform<std::pair<T1, T2>, Fun>::type
|
---|
367 | < call(const std::pair<T1, T2>& t, Fun f)
|
---|
368 | < {
|
---|
369 | < typedef typename tuple_meta_transform<std::pair<T1, T2>, Fun>::type
|
---|
370 | < return_type;
|
---|
371 | <
|
---|
372 | < return return_type( f(t.first), f(t.second) );
|
---|
373 | < }
|
---|
374 | < };
|
---|
375 | <
|
---|
376 | 554a270,277
|
---|
377 | > template<typename Fun>
|
---|
378 | > Fun BOOST_TUPLE_ALGO(tuple_for_each)(
|
---|
379 | > tuples::null_type
|
---|
380 | > , Fun f BOOST_TUPLE_ALGO_TERMINATOR
|
---|
381 | > )
|
---|
382 | > { return f; }
|
---|
383 | >
|
---|
384 | >
|
---|
385 | 556,558c279,282
|
---|
386 | < struct tuple_for_each_impl {
|
---|
387 | < static Fun BOOST_TUPLE_ALGO(call)( Tuple& t, Fun f BOOST_TUPLE_ALGO_RECURSE)
|
---|
388 | < {
|
---|
389 | ---
|
---|
390 | > Fun BOOST_TUPLE_ALGO(tuple_for_each)(
|
---|
391 | > Tuple& t
|
---|
392 | > , Fun f BOOST_TUPLE_ALGO_RECURSE)
|
---|
393 | > {
|
---|
394 | 560,563c284,286
|
---|
395 | < return tuple_for_each_impl<typename Tuple::tail_type,
|
---|
396 | < Fun>::call( t.get_tail(), f);
|
---|
397 | < }
|
---|
398 | <
|
---|
399 | ---
|
---|
400 | > return tuple_for_each(t.get_tail(), f);
|
---|
401 | > }
|
---|
402 | >
|
---|
403 | 565c288,293
|
---|
404 | < static Fun call(Tuple& t, Fun f)
|
---|
405 | ---
|
---|
406 | > template<typename Tuple, typename Fun>
|
---|
407 | > Fun
|
---|
408 | > tuple_for_each(
|
---|
409 | > Tuple& t,
|
---|
410 | > Fun f
|
---|
411 | > )
|
---|
412 | 567c295
|
---|
413 | < return call_impl(t, f, 1);
|
---|
414 | ---
|
---|
415 | > return tuple_for_each_impl(t, f, 1);
|
---|
416 | 570,604d297
|
---|
417 | < };
|
---|
418 | <
|
---|
419 | < template<typename Fun>
|
---|
420 | < struct tuple_for_each_impl<tuples::null_type, Fun> {
|
---|
421 | < inline static Fun call( tuples::null_type,
|
---|
422 | < Fun f BOOST_TUPLE_ALGO_TERMINATOR)
|
---|
423 | < {
|
---|
424 | < return f;
|
---|
425 | < }
|
---|
426 | < };
|
---|
427 | <
|
---|
428 | <
|
---|
429 | < // for_each algorithm for std::tuple
|
---|
430 | < template<typename... Args , typename Fun>
|
---|
431 | < struct tuple_for_each_impl< std::tuple<Args...>, Fun> {
|
---|
432 | <
|
---|
433 | < inline static Fun call(std::tuple<Args...>& t, Fun f)
|
---|
434 | < {
|
---|
435 | < return helper::for_each(t, f);
|
---|
436 | < }
|
---|
437 | <
|
---|
438 | < };
|
---|
439 | <
|
---|
440 | < // for_each algorithm for std::pair
|
---|
441 | < template<typename T1, typename T2 , typename Fun>
|
---|
442 | < struct tuple_for_each_impl< std::pair<T1, T2>, Fun> {
|
---|
443 | <
|
---|
444 | < inline static Fun call(std::pair<T1, T2>& t, Fun f)
|
---|
445 | < {
|
---|
446 | < f(t.first);
|
---|
447 | < f(t.second);
|
---|
448 | < return f;
|
---|
449 | < }
|
---|
450 | <
|
---|
451 | < };
|
---|
452 | 611,665c304,305
|
---|
453 | < template<typename Tuple1, typename Tuple2>
|
---|
454 | < struct tuple_equal_impl{
|
---|
455 | < static bool call(const Tuple1& t1, const Tuple2& t2){
|
---|
456 | < return t1.get_head() == t2.get_head() &&
|
---|
457 | < tuple_equal(t1.get_tail(), t2.get_tail());
|
---|
458 | < }
|
---|
459 | < };
|
---|
460 | <
|
---|
461 | < template<>
|
---|
462 | < struct tuple_equal_impl<tuples::null_type, tuples::null_type> {
|
---|
463 | < inline static bool call(tuples::null_type, tuples::null_type){
|
---|
464 | < return true;
|
---|
465 | < }
|
---|
466 | < };
|
---|
467 | <
|
---|
468 | < // Equality of std::tuples.
|
---|
469 | < template<class... Args1, class... Args2>
|
---|
470 | < struct tuple_equal_impl< std::tuple<Args1...>, std::tuple<Args2...> > {
|
---|
471 | <
|
---|
472 | < inline static bool call( const std::tuple<Args1...>& t1,
|
---|
473 | < const std::tuple<Args2...>& t2 )
|
---|
474 | < {
|
---|
475 | < return t1 == t2;
|
---|
476 | < }
|
---|
477 | < };
|
---|
478 | <
|
---|
479 | < // Equality of std::pair
|
---|
480 | < template<class T1, class T2, class U1, class U2>
|
---|
481 | < struct tuple_equal_impl< std::pair<T1, T2>, std::pair<U1, U2> > {
|
---|
482 | <
|
---|
483 | < inline static bool call( const std::pair<T1, T2>& t1,
|
---|
484 | < const std::pair<U1, U2>& t2 )
|
---|
485 | < {
|
---|
486 | < return t1 == t2;
|
---|
487 | < }
|
---|
488 | < };
|
---|
489 | <
|
---|
490 | < }//namespace detail
|
---|
491 | <
|
---|
492 | <
|
---|
493 | < //Forward template functions to respective implementations
|
---|
494 | <
|
---|
495 | < template<class Tuple, class Fun>
|
---|
496 | < inline typename tuple_meta_transform<Tuple, Fun>::type
|
---|
497 | < tuple_transform(const Tuple& t, Fun f)
|
---|
498 | < {
|
---|
499 | < return detail::tuple_transform_impl<Tuple, Fun>::call(t, f);
|
---|
500 | < }
|
---|
501 | <
|
---|
502 | <
|
---|
503 | < template<typename Tuple, typename Fun>
|
---|
504 | < inline Fun tuple_for_each(Tuple& t, Fun f)
|
---|
505 | < {
|
---|
506 | < return detail::tuple_for_each_impl<Tuple, Fun>::call(t, f);
|
---|
507 | < }
|
---|
508 | ---
|
---|
509 | > inline bool tuple_equal(tuples::null_type, tuples::null_type)
|
---|
510 | > { return true; }
|
---|
511 | 668c308,311
|
---|
512 | < inline bool tuple_equal(Tuple1 const& t1, Tuple2 const& t2)
|
---|
513 | ---
|
---|
514 | > bool tuple_equal(
|
---|
515 | > Tuple1 const& t1,
|
---|
516 | > Tuple2 const& t2
|
---|
517 | > )
|
---|
518 | 670c313,314
|
---|
519 | < return detail::tuple_equal_impl<Tuple1, Tuple2>::call(t1, t2);
|
---|
520 | ---
|
---|
521 | > return t1.get_head() == t2.get_head() &&
|
---|
522 | > tuple_equal(t1.get_tail(), t2.get_tail());
|
---|