1 // Boost.TypeErasure library
2 //
3 // Copyright 2011-2012 Steven Watanabe
4 //
5 // Distributed under the Boost Software License Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // $Id$
10 
11 #if !defined(BOOST_PP_IS_ITERATING)
12 
13 #ifndef BOOST_TYPE_ERASURE_TUPLE_HPP_INCLUDED
14 #define BOOST_TYPE_ERASURE_TUPLE_HPP_INCLUDED
15 
16 #include <boost/config.hpp>
17 
18 
19 #ifdef BOOST_TYPE_ERASURE_DOXYGEN
20 
21 namespace boost {
22 namespace type_erasure {
23 
24 /**
25  * @ref tuple is a Boost.Fusion Random Access Sequence containing
26  * @ref any "anys". @c Concept specifies the \Concept for each
27  * of the elements.  The remaining arguments must be (possibly const
28  * and/or reference qualified) placeholders, which are the
29  * @ref placeholder "placeholders" of the elements.
30  */
31 template<class Concept, class... T>
32 class tuple
33 {
34 public:
35     /**
36      * Constructs a tuple.  Each element of @c args will
37      * be used to initialize the corresponding @ref any member.
38      * The @ref binding for the tuple elements is determined
39      * by mapping the placeholders in @c T to the corresponding
40      * types in @c U.
41      */
42     template<class... U>
43     explicit tuple(U&&... args);
44 };
45 
46 /**
47  * Returns the Nth @ref any in the tuple.
48  */
49 template<int N, class Concept, class... T>
50 any<Concept, TN>& get(tuple<Concept, T...>& arg);
51 /** \overload */
52 template<int N, class Concept, class... T>
53 const any<Concept, TN>& get(const tuple<Concept, T...>& arg);
54 
55 }
56 }
57 
58 #elif !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
59 
60 #include <boost/mpl/int.hpp>
61 #include <boost/mpl/bool.hpp>
62 #include <boost/mpl/map.hpp>
63 #include <boost/mpl/insert.hpp>
64 #include <boost/type_traits/remove_reference.hpp>
65 #include <boost/type_traits/remove_const.hpp>
66 #include <boost/fusion/include/category_of.hpp>
67 #include <boost/fusion/include/iterator_facade.hpp>
68 #include <boost/fusion/include/sequence_facade.hpp>
69 #include <boost/type_erasure/any.hpp>
70 #include <boost/type_erasure/static_binding.hpp>
71 #include <boost/type_erasure/config.hpp>
72 
73 namespace boost {
74 namespace type_erasure {
75 
76 template<class Concept, class... T>
77 struct cons;
78 
79 template<class Concept>
80 struct cons<Concept>
81 {
82     template<class Binding>
consboost::type_erasure::cons83     cons(const Binding&) {}
84 };
85 
86 template<class Concept, class T0, class... T>
87 struct cons<Concept, T0, T...>
88 {
89     typedef any<Concept, T0> value_type;
90     typedef cons<Concept, T...> rest_type;
91     template<class Binding, class U0, class... U>
consboost::type_erasure::cons92     cons(const Binding& b, U0&& u0, U&&... u)
93       : value(std::forward<U0>(u0), b),
94         rest(b, std::forward<U>(u)...)
95     {}
96     any<Concept, T0> value;
97     cons<Concept, T...> rest;
98 };
99 
100 namespace detail {
101 
102 template<int N, class Cons>
103 struct cons_advance
104 {
105     typedef typename cons_advance<N-1, Cons>::type::rest_type type;
callboost::type_erasure::detail::cons_advance106     static const type& call(const Cons& c)
107     {
108         return cons_advance<N-1, Cons>::call(c).rest;
109     }
110 };
111 
112 template<class Cons>
113 struct cons_advance<0, Cons>
114 {
115     typedef Cons type;
callboost::type_erasure::detail::cons_advance116     static const type& call(const Cons& c)
117     {
118         return c;
119     }
120 };
121 
122 template<class... T>
123 struct make_map;
124 
125 template<class T0, class... T>
126 struct make_map<T0, T...>
127 {
128     typedef typename ::boost::mpl::insert<
129         typename ::boost::type_erasure::detail::make_map<T...>::type,
130         T0
131     >::type type;
132 };
133 
134 template<>
135 struct make_map<>
136 {
137     typedef ::boost::mpl::map0<> type;
138 };
139 
140 }
141 
142 /** INTERNAL ONLY */
143 template<class Tuple, int N>
144 class tuple_iterator :
145     public ::boost::fusion::iterator_facade<
146         tuple_iterator<Tuple, N>,
147         ::boost::fusion::random_access_traversal_tag
148     >
149 {
150 public:
151     typedef ::boost::mpl::int_<N> index;
tuple_iterator(Tuple & t_arg)152     explicit tuple_iterator(Tuple& t_arg) : t(&t_arg) {}
153     template<class It>
154     struct value_of
155     {
156         typedef typename Tuple::template value_at<Tuple, mpl::int_<N> >::type type;
157     };
158     template<class It>
159     struct deref
160     {
161         typedef typename Tuple::template at<Tuple, mpl::int_<N> >::type type;
callboost::type_erasure::tuple_iterator::deref162         static type call(It it)
163         {
164             return Tuple::template at<Tuple, mpl::int_<N> >::call(*it.t);
165         }
166     };
167     template<class It, class M>
168     struct advance
169     {
170         typedef tuple_iterator<Tuple, (It::index::value+M::value)> type;
callboost::type_erasure::tuple_iterator::advance171         static type call(It it) { return type(*it.t); }
172     };
173     template<class It>
174     struct next : advance<It, ::boost::mpl::int_<1> > {};
175     template<class It>
176     struct prior : advance<It, ::boost::mpl::int_<-1> > {};
177     template<class It1, class It2>
178     struct distance
179     {
180         typedef typename ::boost::mpl::minus<
181             typename It2::index,
182             typename It1::index
183         >::type type;
callboost::type_erasure::tuple_iterator::distance184         static type call(It1, It2) { return type(); }
185     };
186 private:
187     Tuple* t;
188 };
189 
190 template<class Concept, class... T>
191 class tuple :
192     public ::boost::fusion::sequence_facade<
193         ::boost::type_erasure::tuple<Concept, T...>,
194         ::boost::fusion::forward_traversal_tag
195     >
196 {
197 public:
198     template<class... U>
tuple(U &&...args)199     explicit tuple(U&&... args)
200       : impl(
201             ::boost::type_erasure::make_binding<
202                 typename ::boost::type_erasure::detail::make_map<
203                     ::boost::mpl::pair<
204                         typename ::boost::remove_const<
205                             typename ::boost::remove_reference<T>::type
206                         >::type,
207                         typename ::boost::remove_const<
208                             typename ::boost::remove_reference<U>::type
209                         >::type
210                     >...
211                 >::type
212             >(),
213             std::forward<U>(args)...)
214     {}
215 
216     template<class Seq>
217     struct begin
218     {
219         typedef ::boost::type_erasure::tuple_iterator<
220             Seq,
221             0
222         > type;
callboost::type_erasure::tuple::begin223         static type call(Seq& seq) { return type(seq); }
224     };
225     template<class Seq>
226     struct end
227     {
228         typedef ::boost::type_erasure::tuple_iterator<
229             Seq,
230             sizeof...(T)
231         > type;
callboost::type_erasure::tuple::end232         static type call(Seq& seq) { return type(seq); }
233     };
234     template<class Seq>
235     struct size
236     {
237         typedef ::boost::mpl::int_<sizeof...(T)> type;
callboost::type_erasure::tuple::size238         static type call(Seq& seq) { return type(); }
239     };
240     template<class Seq>
241     struct empty
242     {
243         typedef ::boost::mpl::bool_<sizeof...(T) == 0> type;
callboost::type_erasure::tuple::empty244         static type call(Seq& seq) { return type(); }
245     };
246     template<class Seq, class N>
247     struct at
248     {
249         typedef typename ::boost::type_erasure::detail::cons_advance<
250             N::value,
251             ::boost::type_erasure::cons<Concept, T...>
252         >::type::value_type value_type;
253         typedef typename ::boost::mpl::if_< ::boost::is_const<Seq>,
254             const value_type&,
255             value_type&
256         >::type type;
callboost::type_erasure::tuple::at257         static type call(Seq& seq)
258         {
259             return const_cast<type>(
260                 ::boost::type_erasure::detail::cons_advance<
261                     N::value,
262                     ::boost::type_erasure::cons<Concept, T...>
263                 >::call(seq.impl).value
264             );
265         }
266     };
267     template<class Seq, class N>
268     struct value_at
269     {
270         typedef typename ::boost::type_erasure::detail::cons_advance<
271             N::value,
272             ::boost::type_erasure::cons<Concept, T...>
273         >::type::value_type value_type;
274     };
275     ::boost::type_erasure::cons<Concept, T...> impl;
276 };
277 
278 template<int N, class Concept, class... T>
279 typename ::boost::type_erasure::detail::cons_advance<
280     N,
281     ::boost::type_erasure::cons<Concept, T...>
get(::boost::type_erasure::tuple<Concept,T...> & t)282 >::type::value_type& get(::boost::type_erasure::tuple<Concept, T...>& t)
283 {
284     return const_cast<
285         typename ::boost::type_erasure::detail::cons_advance<
286             N,
287             ::boost::type_erasure::cons<Concept, T...>
288         >::type::value_type&
289     >(
290         ::boost::type_erasure::detail::cons_advance<N,
291             ::boost::type_erasure::cons<Concept, T...>
292         >::call(t.impl).value
293     );
294 }
295 
296 template<int N, class Concept, class... T>
297 const typename ::boost::type_erasure::detail::cons_advance<
298     N,
299     ::boost::type_erasure::cons<Concept, T...>
get(const::boost::type_erasure::tuple<Concept,T...> & t)300 >::type::value_type& get(const ::boost::type_erasure::tuple<Concept, T...>& t)
301 {
302     return ::boost::type_erasure::detail::cons_advance<
303         N,
304         ::boost::type_erasure::cons<Concept, T...>
305     >::call(t.impl).value;
306 }
307 
308 }
309 }
310 
311 #else
312 
313 #include <boost/mpl/int.hpp>
314 #include <boost/mpl/minus.hpp>
315 #include <boost/mpl/equal_to.hpp>
316 #include <boost/mpl/map.hpp>
317 #include <boost/fusion/include/category_of.hpp>
318 #include <boost/fusion/include/iterator_facade.hpp>
319 #include <boost/fusion/include/sequence_facade.hpp>
320 #include <boost/preprocessor/cat.hpp>
321 #include <boost/preprocessor/iteration/iterate.hpp>
322 #include <boost/preprocessor/repetition/repeat.hpp>
323 #include <boost/preprocessor/repetition/enum.hpp>
324 #include <boost/preprocessor/repetition/enum_params.hpp>
325 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
326 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
327 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
328 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
329 #include <boost/type_erasure/any.hpp>
330 #include <boost/type_erasure/static_binding.hpp>
331 #include <boost/type_erasure/config.hpp>
332 
333 namespace boost {
334 namespace type_erasure {
335 
336 /** INTERNAL ONLY */
337 struct na {};
338 
339 namespace detail {
340 
341 template<int N, class Tuple>
342 struct get_impl;
343 
344 template<class Concept,
345     BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
346         BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, class T, ::boost::type_erasure::na)>
347 struct tuple_storage;
348 
349 }
350 
351 /** INTERNAL ONLY */
352 template<class Tuple, int N>
353 class tuple_iterator :
354     public ::boost::fusion::iterator_facade<
355         tuple_iterator<Tuple, N>,
356         ::boost::fusion::random_access_traversal_tag
357     >
358 {
359 public:
360     typedef ::boost::mpl::int_<N> index;
tuple_iterator(Tuple & t_arg)361     explicit tuple_iterator(Tuple& t_arg) : t(&t_arg) {}
362     template<class It>
363     struct value_of
364     {
365         typedef typename ::boost::type_erasure::detail::get_impl<
366             It::index::value,
367             Tuple
368         >::value_type type;
369     };
370     template<class It>
371     struct deref :
372         ::boost::type_erasure::detail::get_impl<It::index::value, Tuple>
373     {
374         typedef typename ::boost::type_erasure::detail::get_impl<
375             It::index::value,
376             Tuple
377         >::type type;
callboost::type_erasure::tuple_iterator::deref378         static type call(It it)
379         {
380             return ::boost::type_erasure::detail::get_impl<
381                 It::index::value,
382                 Tuple
383             >::call(*it.t);
384         }
385     };
386     template<class It, class M>
387     struct advance
388     {
389         typedef tuple_iterator<Tuple, (It::index::value+M::value)> type;
callboost::type_erasure::tuple_iterator::advance390         static type call(It it) { return type(*it.t); }
391     };
392     template<class It>
393     struct next : advance<It, ::boost::mpl::int_<1> > {};
394     template<class It>
395     struct prior : advance<It, ::boost::mpl::int_<-1> > {};
396     template<class It1, class It2>
397     struct distance
398     {
399         typedef typename ::boost::mpl::minus<
400             typename It2::index,
401             typename It1::index
402         >::type type;
callboost::type_erasure::tuple_iterator::distance403         static type call(It1, It2) { return type(); }
404     };
405 private:
406     Tuple* t;
407 };
408 
409 /** INTERNAL ONLY */
410 template<class Derived>
411 struct tuple_base :
412     ::boost::fusion::sequence_facade<
413         Derived,
414         ::boost::fusion::random_access_traversal_tag
415     >
416 {
417     template<class Seq>
418     struct begin
419     {
420         typedef ::boost::type_erasure::tuple_iterator<Seq, 0> type;
callboost::type_erasure::tuple_base::begin421         static type call(Seq& seq) { return type(seq); }
422     };
423     template<class Seq>
424     struct end
425     {
426         typedef ::boost::type_erasure::tuple_iterator<
427             Seq,
428             Seq::tuple_size::value
429         > type;
callboost::type_erasure::tuple_base::end430         static type call(Seq& seq) { return type(seq); }
431     };
432     template<class Seq>
433     struct size
434     {
435         typedef typename Seq::tuple_size type;
callboost::type_erasure::tuple_base::size436         static type call(Seq& seq) { return type(); }
437     };
438     template<class Seq>
439     struct empty
440     {
441         typedef typename boost::mpl::equal_to<
442             typename Seq::tuple_size,
443             boost::mpl::int_<0>
444         >::type type;
callboost::type_erasure::tuple_base::empty445         static type call(Seq& seq) { return type(); }
446     };
447     template<class Seq, class N>
448     struct at : ::boost::type_erasure::detail::get_impl<N::value, Seq> {};
449     template<class Seq, class N>
450     struct value_at
451     {
452         typedef typename ::boost::type_erasure::detail::get_impl<
453             N::value,
454             Seq
455         >::value_type type;
456     };
457 };
458 
459 template<class Concept,
460     BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
461         BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, class T, ::boost::type_erasure::na)>
462 class tuple;
463 
464 template<
465     int N,
466     class Concept
467     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, class T)
468 >
469 typename detail::get_impl<
470     N,
471     tuple<
472         Concept
473         BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
474     >
get(tuple<Concept BOOST_PP_ENUM_TRAILING_PARAMS (BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE,T)> & arg)475 >::type get(
476     tuple<
477         Concept
478         BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
479     >& arg)
480 {
481     return detail::get_impl<
482         N,
483         tuple<
484             Concept
485             BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
486         >
487     >::call(arg);
488 }
489 
490 template<
491     int N,
492     class Concept
493     BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, class T)
494 >
495 typename detail::get_impl<
496     N,
497     const tuple<
498         Concept
499         BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
500     >
get(const tuple<Concept BOOST_PP_ENUM_TRAILING_PARAMS (BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE,T)> & arg)501 >::type get(
502     const tuple<
503         Concept
504         BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
505     >& arg)
506 {
507     return detail::get_impl<
508         N,
509         const tuple<
510             Concept
511             BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE, T)
512         >
513     >::call(arg);
514 }
515 
516 /** INTERNAL ONLY */
517 #define BOOST_PP_FILENAME_1 <boost/type_erasure/tuple.hpp>
518 /** INTERNAL ONLY */
519 #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE)
520 #include BOOST_PP_ITERATE()
521 
522 }
523 }
524 
525 #endif
526 
527 #endif
528 
529 #else
530 
531 #define N BOOST_PP_ITERATION()
532 
533 #define BOOST_TYPE_ERASURE_TAG_TYPEDEF(z, n, data)                          \
534     typedef BOOST_PP_CAT(T, n) BOOST_PP_CAT(tag_type, n);                   \
535     typedef typename ::boost::remove_reference<BOOST_PP_CAT(T, n)>::type    \
536         BOOST_PP_CAT(tag, n);
537 
538 #define BOOST_TYPE_ERASURE_PAIR(z, n, data) \
539     ::boost::mpl::pair<BOOST_PP_CAT(tag, n), BOOST_PP_CAT(U, n)>
540 
541 #define BOOST_TYPE_ERASURE_CONSTRUCT(z, n, data)\
542     BOOST_PP_CAT(t, n)(BOOST_PP_CAT(u, n), table)
543 
544 #define BOOST_TYPE_ERASURE_TUPLE_MEMBER(z, n, data)\
545     ::boost::type_erasure::any<Concept, BOOST_PP_CAT(T, n)> BOOST_PP_CAT(t, n);
546 
547 #if N == 1
548 #define BOOST_TYPE_ERASURE_EXPLICIT explicit
549 #else
550 #define BOOST_TYPE_ERASURE_EXPLICIT
551 #endif
552 
553 namespace detail {
554 
555 template<class Concept BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)>
556 struct tuple_storage
557 #if N != BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE
558     <Concept BOOST_PP_ENUM_TRAILING_PARAMS(N, T)>
559 #endif
560 {
561 #if N
562     template<class Table BOOST_PP_ENUM_TRAILING_PARAMS(N, class U)>
tuple_storagedetail::tuple_storage563     tuple_storage(
564         const Table& table BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, &u))
565         :
566         BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_CONSTRUCT, ~) {}
567 #else
568     template<class Table>
569     explicit tuple_storage(const Table&) {}
570 #endif
571     BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_TUPLE_MEMBER, `)
572 };
573 
574 #if N != BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE
575 
576 template<class Tuple>
577 struct get_impl<N, Tuple>
578 {
579     typedef any<
580         typename Tuple::concept_type,
581         typename Tuple::BOOST_PP_CAT(tag_type, N)
582     > value_type;
583     typedef value_type& type;
calldetail::get_impl584     static type call(Tuple& arg)
585     { return arg.impl.BOOST_PP_CAT(t, N); }
586 };
587 
588 template<class Tuple>
589 struct get_impl<N, const Tuple>
590 {
591     typedef any<
592         typename Tuple::concept_type,
593         typename Tuple::BOOST_PP_CAT(tag_type, N)
594     > value_type;
595     typedef const value_type& type;
calldetail::get_impl596     static type call(const Tuple& arg)
597     { return arg.impl.BOOST_PP_CAT(t, N); }
598 };
599 
600 #endif
601 
602 }
603 
604 template<class Concept BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)>
605 class tuple
606 #if N != BOOST_TYPE_ERASURE_MAX_TUPLE_SIZE
607     <Concept BOOST_PP_ENUM_TRAILING_PARAMS(N, T)>
608 #endif
609     : public tuple_base<tuple<Concept BOOST_PP_ENUM_TRAILING_PARAMS(N, T)> >
610 {
611     typedef Concept concept_type;
612     BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_TAG_TYPEDEF, ~)
613 public:
614     typedef ::boost::mpl::int_<N> tuple_size;
615 #if N
616     template<BOOST_PP_ENUM_PARAMS(N, class U)>
617 #endif
618     BOOST_TYPE_ERASURE_EXPLICIT
tuple(BOOST_PP_ENUM_BINARY_PARAMS (N,U,& u))619     tuple(BOOST_PP_ENUM_BINARY_PARAMS(N, U, &u)) :
620         impl(
621             ::boost::type_erasure::make_binding<
622                 ::boost::mpl::map<
623                     BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_PAIR, ~)
624                 >
625             >()
626             BOOST_PP_ENUM_TRAILING_PARAMS(N, u)
627         )
628     {}
629 #if N
630     template<BOOST_PP_ENUM_PARAMS(N, class U)>
631     BOOST_TYPE_ERASURE_EXPLICIT
tuple(BOOST_PP_ENUM_BINARY_PARAMS (N,const U,& u))632     tuple(BOOST_PP_ENUM_BINARY_PARAMS(N, const U, &u)) :
633         impl(
634             ::boost::type_erasure::make_binding<
635                 ::boost::mpl::map<
636                     BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_PAIR, ~)
637                 >
638             >()
639             BOOST_PP_ENUM_TRAILING_PARAMS(N, u)
640         )
641     {}
642 #endif
643 private:
644     template<int M, class Tuple>
645     friend struct ::boost::type_erasure::detail::get_impl;
646     ::boost::type_erasure::detail::tuple_storage<
647         Concept
648         BOOST_PP_ENUM_TRAILING_PARAMS(N, T)
649     > impl;
650 };
651 
652 #undef BOOST_TYPE_ERASURE_EXPLICIT
653 #undef BOOST_TYPE_ERASURE_TUPLE_MEMBER
654 #undef BOOST_TYPE_ERASURE_CONSTRUCT
655 #undef BOOST_TYPE_ERASURE_PAIR
656 #undef BOOST_TYPE_ERASURE_TAG_TYPEDEF
657 #undef N
658 
659 #endif
660