1 // - tuple_basic_no_partial_spec.hpp -----------------------------------------
3 // Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
4 // Copyright (C) 2001 Doug Gregor (gregod@rpi.edu)
5 // Copyright (C) 2001 Gary Powell (gary.powell@sierra.com)
7 // Permission to copy, use, sell and distribute this software is granted
8 // provided this copyright notice appears in all copies.
9 // Permission to modify the code and to distribute modified code is granted
10 // provided this copyright notice appears in all copies, and a notice
11 // that the code was modified is included with the copyright notice.
13 // This software is provided "as is" without express or implied warranty,
14 // and with no claim as to its suitability for any purpose.
16 // For more information, see http://www.boost.org or http://lambda.cs.utu.fi
19 // 14 02 01 Remove extra ';'. Also, fixed 10-parameter to make_tuple. (DG)
20 // 10 02 01 Fixed "null_type" constructors.
21 // Implemented comparison operators globally.
22 // Hide element_type_ref and element_type_const_ref.
24 // 09 02 01 Extended to tuples of length 10. Changed comparison for
26 // to the same used by std::pair<>, added cnull_type() (GP)
27 // 03 02 01 Initial Version from original tuple.hpp code by JJ. (DG)
29 // -----------------------------------------------------------------
31 #ifndef BOOST_TUPLE_BASIC_NO_PARTIAL_SPEC_HPP
32 #define BOOST_TUPLE_BASIC_NO_PARTIAL_SPEC_HPP
34 #include "boost/type_traits.hpp"
36 #if defined BOOST_MSVC
37 #pragma warning(disable:4518) // storage-class or type specifier(s) unexpected here; ignored
38 #pragma warning(disable:4181) // qualifier applied to reference type ignored
39 #pragma warning(disable:4227) // qualifier applied to reference type ignored
44 // null_type denotes the end of a list built with "cons"
48 null_type(const null_type&, const null_type&) {}
51 // a helper function to provide a const null_type type temporary
52 inline const null_type cnull_type() { return null_type(); }
56 // Takes a pointer and routes all assignments to whatever it points to
58 struct assign_to_pointee
61 explicit assign_to_pointee(T* p) : ptr(p) {}
63 template<typename Other>
64 assign_to_pointee& operator=(const Other& other)
74 // Swallows any assignment
78 swallow_assign& operator=(const T&)
84 } // end of namespace tuples
85 } // end of namespace detail
87 // cons builds a heterogenous list of types
88 template<typename Head, typename Tail = null_type>
91 typedef cons self_type;
92 typedef Head head_type;
93 typedef Tail tail_type;
98 typename boost::add_reference<head_type>::type get_head() { return head; }
99 typename boost::add_reference<tail_type>::type get_tail() { return tail; }
101 typename boost::add_reference<const head_type>::type get_head() const { return head; }
102 typename boost::add_reference<const tail_type>::type get_tail() const { return tail; }
104 template<typename Other>
105 explicit cons(const Other& other) : head(other.head), tail(other.tail)
109 #if defined BOOST_MSVC
110 explicit cons(const head_type& h /* = head_type() */, // causes MSVC 6.5 to barf.
111 const tail_type& t = tail_type()) :
116 explicit cons(const head_type& h = head_type(),
117 const tail_type& t = tail_type()) :
124 template<typename Other>
125 cons& operator=(const Other& other)
135 // Determines if the parameter is null_type
136 template<typename T> struct is_null_type { enum { RET = 0 }; };
137 template<> struct is_null_type<null_type> { enum { RET = 1 }; };
139 /* Build a cons structure from the given Head and Tail. If both are null_type,
141 template<typename Head, typename Tail>
145 enum { tail_is_null_type = is_null_type<Tail>::RET };
147 typedef cons<Head, Tail> RET;
151 struct build_cons<null_type, null_type>
153 typedef null_type RET;
156 // Map the N elements of a tuple into a cons list
159 typename T2 = null_type,
160 typename T3 = null_type,
161 typename T4 = null_type,
162 typename T5 = null_type,
163 typename T6 = null_type,
164 typename T7 = null_type,
165 typename T8 = null_type,
166 typename T9 = null_type,
167 typename T10 = null_type
169 struct map_tuple_to_cons
171 typedef typename detail::tuples::build_cons<T10, null_type >::RET cons10;
172 typedef typename detail::tuples::build_cons<T9, cons10>::RET cons9;
173 typedef typename detail::tuples::build_cons<T8, cons9>::RET cons8;
174 typedef typename detail::tuples::build_cons<T7, cons8>::RET cons7;
175 typedef typename detail::tuples::build_cons<T6, cons7>::RET cons6;
176 typedef typename detail::tuples::build_cons<T5, cons6>::RET cons5;
177 typedef typename detail::tuples::build_cons<T4, cons5>::RET cons4;
178 typedef typename detail::tuples::build_cons<T3, cons4>::RET cons3;
179 typedef typename detail::tuples::build_cons<T2, cons3>::RET cons2;
180 typedef typename detail::tuples::build_cons<T1, cons2>::RET cons1;
183 // Workaround the lack of partial specialization in some compilers
187 template<typename Tuple>
191 typedef typename Tuple::tail_type tail_type;
192 typedef _element_type<N-1> next_elt_type;
195 typedef typename _element_type<N-1>::template inner<tail_type>::RET RET;
200 struct _element_type<0>
202 template<typename Tuple>
205 typedef typename Tuple::head_type RET;
211 // Return the Nth type of the given Tuple
212 template<int N, typename Tuple>
216 typedef detail::tuples::_element_type<N> nth_type;
219 typedef typename nth_type::template inner<Tuple>::RET RET;
225 // Return a reference to the Nth type of the given Tuple
226 template<int N, typename Tuple>
227 struct tuple_element_ref
230 typedef typename tuple_element<N, Tuple>::RET elt_type;
233 typedef typename add_reference<elt_type>::type RET;
237 // Return a const reference to the Nth type of the given Tuple
238 template<int N, typename Tuple>
239 struct tuple_element_const_ref
242 typedef typename tuple_element<N, Tuple>::RET elt_type;
245 typedef typename add_reference<const elt_type>::type RET;
250 // Get length of this tuple
251 template<typename Tuple>
254 enum { value = 1 + tuple_length<typename Tuple::tail_type>::value };
258 struct tuple_length<null_type>
263 // Reference the Nth element in a tuple and retrieve it with "get"
267 template<typename Tuple>
269 typename detail::tuples::tuple_element_ref<N, Tuple>::RET
272 return element<N-1>::get(t.tail);
275 template<typename Tuple>
277 typename detail::tuples::tuple_element_const_ref<N, Tuple>::RET
280 return element<N-1>::get(t.tail);
287 template<typename Tuple>
289 typename add_reference<typename Tuple::head_type>::type
295 template<typename Tuple>
297 typename add_reference<const typename Tuple::head_type>::type
307 typename T2 = null_type,
308 typename T3 = null_type,
309 typename T4 = null_type,
310 typename T5 = null_type,
311 typename T6 = null_type,
312 typename T7 = null_type,
313 typename T8 = null_type,
314 typename T9 = null_type,
315 typename T10 = null_type
318 public detail::tuples::map_tuple_to_cons<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>::cons1
321 typedef detail::tuples::map_tuple_to_cons<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> mapped_tuple;
322 typedef typename mapped_tuple::cons10 cons10;
323 typedef typename mapped_tuple::cons9 cons9;
324 typedef typename mapped_tuple::cons8 cons8;
325 typedef typename mapped_tuple::cons7 cons7;
326 typedef typename mapped_tuple::cons6 cons6;
327 typedef typename mapped_tuple::cons5 cons5;
328 typedef typename mapped_tuple::cons4 cons4;
329 typedef typename mapped_tuple::cons3 cons3;
330 typedef typename mapped_tuple::cons2 cons2;
331 typedef typename mapped_tuple::cons1 cons1;
334 typedef tuple self_type;
336 explicit tuple(const T1& t1 = T1(),
345 const T10& t10 = T10()) :
346 cons1(t1, cons2(t2, cons3(t3, cons4(t4, cons5(t5, cons6(t6,cons7(t7,cons8(t8,cons9(t9,cons10(t10))))))))))
350 template<typename Other>
351 explicit tuple(const Other& other) : cons1(other)
355 template<typename Other>
356 self_type& operator=(const Other& other)
358 this->head = other.head;
359 this->tail = other.tail;
364 // Retrieve the Nth element in the typle
365 template<int N, typename Tuple>
366 typename detail::tuples::tuple_element_ref<N, Tuple>::RET
369 return element<N>::get(t);
372 // Retrieve the Nth element in the typle
373 template<int N, typename Tuple>
374 typename detail::tuples::tuple_element_const_ref<N, Tuple>::RET
377 return element<N>::get(t);
381 template<typename T1>
384 make_tuple(const T1& t1)
386 return tuple<T1>(t1);
390 template<typename T1, typename T2>
393 make_tuple(const T1& t1, const T2& t2)
395 return tuple<T1, T2>(t1, t2);
399 template<typename T1, typename T2, typename T3>
402 make_tuple(const T1& t1, const T2& t2, const T3& t3)
404 return tuple<T1, T2, T3>(t1, t2, t3);
408 template<typename T1, typename T2, typename T3, typename T4>
410 tuple<T1, T2, T3, T4>
411 make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
413 return tuple<T1, T2, T3, T4>(t1, t2, t3, t4);
417 template<typename T1, typename T2, typename T3, typename T4, typename T5>
419 tuple<T1, T2, T3, T4, T5>
420 make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5)
422 return tuple<T1, T2, T3, T4, T5>(t1, t2, t3, t4, t5);
426 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
428 tuple<T1, T2, T3, T4, T5, T6>
429 make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6)
431 return tuple<T1, T2, T3, T4, T5, T6>(t1, t2, t3, t4, t5, t6);
435 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
437 tuple<T1, T2, T3, T4, T5, T6, T7>
438 make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7)
440 return tuple<T1, T2, T3, T4, T5, T6, T7>(t1, t2, t3, t4, t5, t6, t7);
444 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
446 tuple<T1, T2, T3, T4, T5, T6, T7, T8>
447 make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8)
449 return tuple<T1, T2, T3, T4, T5, T6, T7, T8>(t1, t2, t3, t4, t5, t6, t7, t8);
453 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
455 tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>
456 make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9)
458 return tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>(t1, t2, t3, t4, t5, t6, t7, t8, t9);
462 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
464 tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
465 make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9, const T10& t10)
467 return tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
470 // Tie variables into a tuple
471 template<typename T1>
473 tuple<detail::tuples::assign_to_pointee<T1> >
476 return make_tuple(detail::tuples::assign_to_pointee<T1>(&t1));
479 // Tie variables into a tuple
480 template<typename T1, typename T2>
482 tuple<detail::tuples::assign_to_pointee<T1>,
483 detail::tuples::assign_to_pointee<T2> >
486 return make_tuple(detail::tuples::assign_to_pointee<T1>(&t1),
487 detail::tuples::assign_to_pointee<T2>(&t2));
490 // Tie variables into a tuple
491 template<typename T1, typename T2, typename T3>
493 tuple<detail::tuples::assign_to_pointee<T1>,
494 detail::tuples::assign_to_pointee<T2>,
495 detail::tuples::assign_to_pointee<T3> >
496 tie(T1& t1, T2& t2, T3& t3)
498 return make_tuple(detail::tuples::assign_to_pointee<T1>(&t1),
499 detail::tuples::assign_to_pointee<T2>(&t2),
500 detail::tuples::assign_to_pointee<T3>(&t3));
503 // Tie variables into a tuple
504 template<typename T1, typename T2, typename T3, typename T4>
506 tuple<detail::tuples::assign_to_pointee<T1>,
507 detail::tuples::assign_to_pointee<T2>,
508 detail::tuples::assign_to_pointee<T3>,
509 detail::tuples::assign_to_pointee<T4> >
510 tie(T1& t1, T2& t2, T3& t3, T4& t4)
512 return make_tuple(detail::tuples::assign_to_pointee<T1>(&t1),
513 detail::tuples::assign_to_pointee<T2>(&t2),
514 detail::tuples::assign_to_pointee<T3>(&t3),
515 detail::tuples::assign_to_pointee<T4>(&t4));
518 // Tie variables into a tuple
519 template<typename T1, typename T2, typename T3, typename T4, typename T5>
521 tuple<detail::tuples::assign_to_pointee<T1>,
522 detail::tuples::assign_to_pointee<T2>,
523 detail::tuples::assign_to_pointee<T3>,
524 detail::tuples::assign_to_pointee<T4>,
525 detail::tuples::assign_to_pointee<T5> >
526 tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5)
528 return make_tuple(detail::tuples::assign_to_pointee<T1>(&t1),
529 detail::tuples::assign_to_pointee<T2>(&t2),
530 detail::tuples::assign_to_pointee<T3>(&t3),
531 detail::tuples::assign_to_pointee<T4>(&t4),
532 detail::tuples::assign_to_pointee<T5>(&t5));
535 // Tie variables into a tuple
536 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
538 tuple<detail::tuples::assign_to_pointee<T1>,
539 detail::tuples::assign_to_pointee<T2>,
540 detail::tuples::assign_to_pointee<T3>,
541 detail::tuples::assign_to_pointee<T4>,
542 detail::tuples::assign_to_pointee<T5>,
543 detail::tuples::assign_to_pointee<T6> >
544 tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5, T6 &t6)
546 return make_tuple(detail::tuples::assign_to_pointee<T1>(&t1),
547 detail::tuples::assign_to_pointee<T2>(&t2),
548 detail::tuples::assign_to_pointee<T3>(&t3),
549 detail::tuples::assign_to_pointee<T4>(&t4),
550 detail::tuples::assign_to_pointee<T6>(&t5),
551 detail::tuples::assign_to_pointee<T5>(&t6));
554 // Tie variables into a tuple
555 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
557 tuple<detail::tuples::assign_to_pointee<T1>,
558 detail::tuples::assign_to_pointee<T2>,
559 detail::tuples::assign_to_pointee<T3>,
560 detail::tuples::assign_to_pointee<T4>,
561 detail::tuples::assign_to_pointee<T5>,
562 detail::tuples::assign_to_pointee<T6>,
563 detail::tuples::assign_to_pointee<T7> >
564 tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5, T6 &t6, T7 &t7)
566 return make_tuple(detail::tuples::assign_to_pointee<T1>(&t1),
567 detail::tuples::assign_to_pointee<T2>(&t2),
568 detail::tuples::assign_to_pointee<T3>(&t3),
569 detail::tuples::assign_to_pointee<T4>(&t4),
570 detail::tuples::assign_to_pointee<T5>(&t5),
571 detail::tuples::assign_to_pointee<T6>(&t6),
572 detail::tuples::assign_to_pointee<T7>(&t7));
575 // Tie variables into a tuple
576 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
578 tuple<detail::tuples::assign_to_pointee<T1>,
579 detail::tuples::assign_to_pointee<T2>,
580 detail::tuples::assign_to_pointee<T3>,
581 detail::tuples::assign_to_pointee<T4>,
582 detail::tuples::assign_to_pointee<T5>,
583 detail::tuples::assign_to_pointee<T6>,
584 detail::tuples::assign_to_pointee<T7>,
585 detail::tuples::assign_to_pointee<T8> >
586 tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5, T6 &t6, T7 &t7, T8 &t8)
588 return make_tuple(detail::tuples::assign_to_pointee<T1>(&t1),
589 detail::tuples::assign_to_pointee<T2>(&t2),
590 detail::tuples::assign_to_pointee<T3>(&t3),
591 detail::tuples::assign_to_pointee<T4>(&t4),
592 detail::tuples::assign_to_pointee<T5>(&t5),
593 detail::tuples::assign_to_pointee<T6>(&t6),
594 detail::tuples::assign_to_pointee<T7>(&t7),
595 detail::tuples::assign_to_pointee<T8>(&t8));
598 // Tie variables into a tuple
599 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
601 tuple<detail::tuples::assign_to_pointee<T1>,
602 detail::tuples::assign_to_pointee<T2>,
603 detail::tuples::assign_to_pointee<T3>,
604 detail::tuples::assign_to_pointee<T4>,
605 detail::tuples::assign_to_pointee<T5>,
606 detail::tuples::assign_to_pointee<T6>,
607 detail::tuples::assign_to_pointee<T7>,
608 detail::tuples::assign_to_pointee<T8>,
609 detail::tuples::assign_to_pointee<T9> >
610 tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5, T6 &t6, T7 &t7, T8 &t8, T9 &t9)
612 return make_tuple(detail::tuples::assign_to_pointee<T1>(&t1),
613 detail::tuples::assign_to_pointee<T2>(&t2),
614 detail::tuples::assign_to_pointee<T3>(&t3),
615 detail::tuples::assign_to_pointee<T4>(&t4),
616 detail::tuples::assign_to_pointee<T5>(&t5),
617 detail::tuples::assign_to_pointee<T6>(&t6),
618 detail::tuples::assign_to_pointee<T7>(&t7),
619 detail::tuples::assign_to_pointee<T8>(&t8),
620 detail::tuples::assign_to_pointee<T9>(&t9));
622 // Tie variables into a tuple
623 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
625 tuple<detail::tuples::assign_to_pointee<T1>,
626 detail::tuples::assign_to_pointee<T2>,
627 detail::tuples::assign_to_pointee<T3>,
628 detail::tuples::assign_to_pointee<T4>,
629 detail::tuples::assign_to_pointee<T5>,
630 detail::tuples::assign_to_pointee<T6>,
631 detail::tuples::assign_to_pointee<T7>,
632 detail::tuples::assign_to_pointee<T8>,
633 detail::tuples::assign_to_pointee<T9>,
634 detail::tuples::assign_to_pointee<T10> >
635 tie(T1& t1, T2& t2, T3& t3, T4& t4, T5 &t5, T6 &t6, T7 &t7, T8 &t8, T9 &t9, T10 &t10)
637 return make_tuple(detail::tuples::assign_to_pointee<T1>(&t1),
638 detail::tuples::assign_to_pointee<T2>(&t2),
639 detail::tuples::assign_to_pointee<T3>(&t3),
640 detail::tuples::assign_to_pointee<T4>(&t4),
641 detail::tuples::assign_to_pointee<T5>(&t5),
642 detail::tuples::assign_to_pointee<T6>(&t6),
643 detail::tuples::assign_to_pointee<T7>(&t7),
644 detail::tuples::assign_to_pointee<T8>(&t8),
645 detail::tuples::assign_to_pointee<T9>(&t9),
646 detail::tuples::assign_to_pointee<T10>(&t10));
648 // "ignore" allows tuple positions to be ignored when using "tie".
650 detail::tuples::swallow_assign ignore;
654 #endif // BOOST_TUPLE_BASIC_NO_PARTIAL_SPEC_HPP