3 // Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file include/tuple
26 * This is a Standard C++ Library header.
29 #ifndef _GLIBCXX_TUPLE
30 #define _GLIBCXX_TUPLE 1
32 #pragma GCC system_header
34 #ifndef __GXX_EXPERIMENTAL_CXX0X__
35 # include <bits/c++0x_warning.h>
40 namespace std _GLIBCXX_VISIBILITY(default)
42 _GLIBCXX_BEGIN_NAMESPACE_VERSION
44 // Adds a const reference to a non-reference type.
45 template<typename _Tp>
47 { typedef const _Tp& type; };
49 template<typename _Tp>
50 struct __add_c_ref<_Tp&>
51 { typedef _Tp& type; };
53 // Adds a reference to a non-reference type.
54 template<typename _Tp>
56 { typedef _Tp& type; };
58 template<typename _Tp>
59 struct __add_ref<_Tp&>
60 { typedef _Tp& type; };
62 template<std::size_t _Idx, typename _Head, bool _IsEmpty>
65 template<std::size_t _Idx, typename _Head>
66 struct _Head_base<_Idx, _Head, true>
69 constexpr _Head_base()
72 constexpr _Head_base(const _Head& __h)
75 template<typename _UHead>
76 _Head_base(_UHead&& __h)
77 : _Head(std::forward<_UHead>(__h)) { }
79 _Head& _M_head() { return *this; }
80 const _Head& _M_head() const { return *this; }
83 _M_swap_impl(_Head& __h)
90 template<std::size_t _Idx, typename _Head>
91 struct _Head_base<_Idx, _Head, false>
93 constexpr _Head_base()
96 constexpr _Head_base(const _Head& __h)
97 : _M_head_impl(__h) { }
99 template<typename _UHead>
100 _Head_base(_UHead&& __h)
101 : _M_head_impl(std::forward<_UHead>(__h)) { }
103 _Head& _M_head() { return _M_head_impl; }
104 const _Head& _M_head() const { return _M_head_impl; }
107 _M_swap_impl(_Head& __h)
110 swap(__h, _M_head());
117 * Contains the actual implementation of the @c tuple template, stored
118 * as a recursive inheritance hierarchy from the first element (most
119 * derived class) to the last (least derived class). The @c Idx
120 * parameter gives the 0-based index of the element stored at this
121 * point in the hierarchy; we use it to implement a constant-time
124 template<std::size_t _Idx, typename... _Elements>
128 * Zero-element tuple implementation. This is the basis case for the
129 * inheritance recursion.
131 template<std::size_t _Idx>
132 struct _Tuple_impl<_Idx>
135 void _M_swap_impl(_Tuple_impl&) { /* no-op */ }
139 * Recursive tuple implementation. Here we store the @c Head element
140 * and derive from a @c Tuple_impl containing the remaining elements
141 * (which contains the @c Tail).
143 template<std::size_t _Idx, typename _Head, typename... _Tail>
144 struct _Tuple_impl<_Idx, _Head, _Tail...>
145 : public _Tuple_impl<_Idx + 1, _Tail...>,
146 private _Head_base<_Idx, _Head, std::is_empty<_Head>::value>
148 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
149 typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base;
151 _Head& _M_head() { return _Base::_M_head(); }
152 const _Head& _M_head() const { return _Base::_M_head(); }
154 _Inherited& _M_tail() { return *this; }
155 const _Inherited& _M_tail() const { return *this; }
157 constexpr _Tuple_impl()
158 : _Inherited(), _Base() { }
161 constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail)
162 : _Inherited(__tail...), _Base(__head) { }
164 template<typename _UHead, typename... _UTail>
166 _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
167 : _Inherited(std::forward<_UTail>(__tail)...),
168 _Base(std::forward<_UHead>(__head)) { }
170 constexpr _Tuple_impl(const _Tuple_impl&) = default;
172 _Tuple_impl(_Tuple_impl&& __in)
173 : _Inherited(std::move(__in._M_tail())),
174 _Base(std::forward<_Head>(__in._M_head())) { }
176 template<typename... _UElements>
177 _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
178 : _Inherited(__in._M_tail()), _Base(__in._M_head()) { }
180 template<typename... _UElements>
181 _Tuple_impl(_Tuple_impl<_Idx, _UElements...>&& __in)
182 : _Inherited(std::move(__in._M_tail())),
183 _Base(std::move(__in._M_head())) { }
186 operator=(const _Tuple_impl& __in)
188 _M_head() = __in._M_head();
189 _M_tail() = __in._M_tail();
194 operator=(_Tuple_impl&& __in)
196 _M_head() = std::move(__in._M_head());
197 _M_tail() = std::move(__in._M_tail());
201 template<typename... _UElements>
203 operator=(const _Tuple_impl<_Idx, _UElements...>& __in)
205 _M_head() = __in._M_head();
206 _M_tail() = __in._M_tail();
210 template<typename... _UElements>
212 operator=(_Tuple_impl<_Idx, _UElements...>&& __in)
214 _M_head() = std::move(__in._M_head());
215 _M_tail() = std::move(__in._M_tail());
221 _M_swap_impl(_Tuple_impl& __in)
223 _Base::_M_swap_impl(__in._M_head());
224 _Inherited::_M_swap_impl(__in._M_tail());
229 template<typename... _Elements>
230 class tuple : public _Tuple_impl<0, _Elements...>
232 typedef _Tuple_impl<0, _Elements...> _Inherited;
239 constexpr tuple(const _Elements&... __elements)
240 : _Inherited(__elements...) { }
242 template<typename... _UElements, typename = typename
243 std::enable_if<sizeof...(_UElements)
244 == sizeof...(_Elements)>::type>
246 tuple(_UElements&&... __elements)
247 : _Inherited(std::forward<_UElements>(__elements)...) { }
249 constexpr tuple(const tuple&) = default;
252 : _Inherited(static_cast<_Inherited&&>(__in)) { }
254 template<typename... _UElements, typename = typename
255 std::enable_if<sizeof...(_UElements)
256 == sizeof...(_Elements)>::type>
257 tuple(const tuple<_UElements...>& __in)
258 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
261 template<typename... _UElements, typename = typename
262 std::enable_if<sizeof...(_UElements)
263 == sizeof...(_Elements)>::type>
264 tuple(tuple<_UElements...>&& __in)
265 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
268 operator=(const tuple& __in)
270 static_cast<_Inherited&>(*this) = __in;
275 operator=(tuple&& __in)
277 static_cast<_Inherited&>(*this) = std::move(__in);
281 template<typename... _UElements, typename = typename
282 std::enable_if<sizeof...(_UElements)
283 == sizeof...(_Elements)>::type>
285 operator=(const tuple<_UElements...>& __in)
287 static_cast<_Inherited&>(*this) = __in;
291 template<typename... _UElements, typename = typename
292 std::enable_if<sizeof...(_UElements)
293 == sizeof...(_Elements)>::type>
295 operator=(tuple<_UElements...>&& __in)
297 static_cast<_Inherited&>(*this) = std::move(__in);
303 { _Inherited::_M_swap_impl(__in); }
310 void swap(tuple&) { /* no-op */ }
313 /// tuple (2-element), with construction and assignment from a pair.
314 template<typename _T1, typename _T2>
315 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
317 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
324 constexpr tuple(const _T1& __a1, const _T2& __a2)
325 : _Inherited(__a1, __a2) { }
327 template<typename _U1, typename _U2>
329 tuple(_U1&& __a1, _U2&& __a2)
330 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
332 constexpr tuple(const tuple&) = default;
335 : _Inherited(static_cast<_Inherited&&>(__in)) { }
337 template<typename _U1, typename _U2>
338 tuple(const tuple<_U1, _U2>& __in)
339 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
341 template<typename _U1, typename _U2>
342 tuple(tuple<_U1, _U2>&& __in)
343 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
345 template<typename _U1, typename _U2>
346 tuple(const pair<_U1, _U2>& __in)
347 : _Inherited(__in.first, __in.second) { }
349 template<typename _U1, typename _U2>
350 tuple(pair<_U1, _U2>&& __in)
351 : _Inherited(std::forward<_U1>(__in.first),
352 std::forward<_U2>(__in.second)) { }
355 operator=(const tuple& __in)
357 static_cast<_Inherited&>(*this) = __in;
362 operator=(tuple&& __in)
364 static_cast<_Inherited&>(*this) = std::move(__in);
368 template<typename _U1, typename _U2>
370 operator=(const tuple<_U1, _U2>& __in)
372 static_cast<_Inherited&>(*this) = __in;
376 template<typename _U1, typename _U2>
378 operator=(tuple<_U1, _U2>&& __in)
380 static_cast<_Inherited&>(*this) = std::move(__in);
384 template<typename _U1, typename _U2>
386 operator=(const pair<_U1, _U2>& __in)
388 this->_M_head() = __in.first;
389 this->_M_tail()._M_head() = __in.second;
393 template<typename _U1, typename _U2>
395 operator=(pair<_U1, _U2>&& __in)
397 this->_M_head() = std::forward<_U1>(__in.first);
398 this->_M_tail()._M_head() = std::forward<_U2>(__in.second);
406 swap(this->_M_head(), __in._M_head());
407 swap(this->_M_tail()._M_head(), __in._M_tail()._M_head());
411 /// tuple (1-element).
412 template<typename _T1>
413 class tuple<_T1> : public _Tuple_impl<0, _T1>
415 typedef _Tuple_impl<0, _T1> _Inherited;
422 constexpr tuple(const _T1& __a1)
423 : _Inherited(__a1) { }
425 template<typename _U1, typename = typename
426 std::enable_if<std::is_convertible<_U1, _T1>::value>::type>
429 : _Inherited(std::forward<_U1>(__a1)) { }
431 constexpr tuple(const tuple&) = default;
434 : _Inherited(static_cast<_Inherited&&>(__in)) { }
436 template<typename _U1>
437 tuple(const tuple<_U1>& __in)
438 : _Inherited(static_cast<const _Tuple_impl<0, _U1>&>(__in)) { }
440 template<typename _U1>
441 tuple(tuple<_U1>&& __in)
442 : _Inherited(static_cast<_Tuple_impl<0, _U1>&&>(__in)) { }
445 operator=(const tuple& __in)
447 static_cast<_Inherited&>(*this) = __in;
452 operator=(tuple&& __in)
454 static_cast<_Inherited&>(*this) = std::move(__in);
458 template<typename _U1>
460 operator=(const tuple<_U1>& __in)
462 static_cast<_Inherited&>(*this) = __in;
466 template<typename _U1>
468 operator=(tuple<_U1>&& __in)
470 static_cast<_Inherited&>(*this) = std::move(__in);
476 { _Inherited::_M_swap_impl(__in); }
480 /// Gives the type of the ith element of a given tuple type.
481 template<std::size_t __i, typename _Tp>
482 struct tuple_element;
485 * Recursive case for tuple_element: strip off the first element in
486 * the tuple and retrieve the (i-1)th element of the remaining tuple.
488 template<std::size_t __i, typename _Head, typename... _Tail>
489 struct tuple_element<__i, tuple<_Head, _Tail...> >
490 : tuple_element<__i - 1, tuple<_Tail...> > { };
493 * Basis case for tuple_element: The first element is the one we're seeking.
495 template<typename _Head, typename... _Tail>
496 struct tuple_element<0, tuple<_Head, _Tail...> >
501 /// Finds the size of a given tuple type.
502 template<typename _Tp>
506 template<typename... _Elements>
507 struct tuple_size<tuple<_Elements...> >
509 static const std::size_t value = sizeof...(_Elements);
512 template<typename... _Elements>
513 const std::size_t tuple_size<tuple<_Elements...> >::value;
515 template<std::size_t __i, typename _Head, typename... _Tail>
516 inline typename __add_ref<_Head>::type
517 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t)
518 { return __t._M_head(); }
520 template<std::size_t __i, typename _Head, typename... _Tail>
521 inline typename __add_c_ref<_Head>::type
522 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t)
523 { return __t._M_head(); }
525 // Return a reference (const reference) to the ith element of a tuple.
526 // Any const or non-const ref elements are returned with their original type.
527 template<std::size_t __i, typename... _Elements>
528 inline typename __add_ref<
529 typename tuple_element<__i, tuple<_Elements...> >::type
531 get(tuple<_Elements...>& __t)
532 { return __get_helper<__i>(__t); }
534 template<std::size_t __i, typename... _Elements>
535 inline typename __add_c_ref<
536 typename tuple_element<__i, tuple<_Elements...> >::type
538 get(const tuple<_Elements...>& __t)
539 { return __get_helper<__i>(__t); }
541 // This class helps construct the various comparison operations on tuples
542 template<std::size_t __check_equal_size, std::size_t __i, std::size_t __j,
543 typename _Tp, typename _Up>
544 struct __tuple_compare;
546 template<std::size_t __i, std::size_t __j, typename _Tp, typename _Up>
547 struct __tuple_compare<0, __i, __j, _Tp, _Up>
549 static bool __eq(const _Tp& __t, const _Up& __u)
551 return (get<__i>(__t) == get<__i>(__u) &&
552 __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__eq(__t, __u));
555 static bool __less(const _Tp& __t, const _Up& __u)
557 return ((get<__i>(__t) < get<__i>(__u))
558 || !(get<__i>(__u) < get<__i>(__t)) &&
559 __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__less(__t, __u));
563 template<std::size_t __i, typename _Tp, typename _Up>
564 struct __tuple_compare<0, __i, __i, _Tp, _Up>
566 static bool __eq(const _Tp&, const _Up&)
569 static bool __less(const _Tp&, const _Up&)
573 template<typename... _TElements, typename... _UElements>
575 operator==(const tuple<_TElements...>& __t,
576 const tuple<_UElements...>& __u)
578 typedef tuple<_TElements...> _Tp;
579 typedef tuple<_UElements...> _Up;
580 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value,
581 0, tuple_size<_Tp>::value, _Tp, _Up>::__eq(__t, __u));
584 template<typename... _TElements, typename... _UElements>
586 operator<(const tuple<_TElements...>& __t,
587 const tuple<_UElements...>& __u)
589 typedef tuple<_TElements...> _Tp;
590 typedef tuple<_UElements...> _Up;
591 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value,
592 0, tuple_size<_Tp>::value, _Tp, _Up>::__less(__t, __u));
595 template<typename... _TElements, typename... _UElements>
597 operator!=(const tuple<_TElements...>& __t,
598 const tuple<_UElements...>& __u)
599 { return !(__t == __u); }
601 template<typename... _TElements, typename... _UElements>
603 operator>(const tuple<_TElements...>& __t,
604 const tuple<_UElements...>& __u)
605 { return __u < __t; }
607 template<typename... _TElements, typename... _UElements>
609 operator<=(const tuple<_TElements...>& __t,
610 const tuple<_UElements...>& __u)
611 { return !(__u < __t); }
613 template<typename... _TElements, typename... _UElements>
615 operator>=(const tuple<_TElements...>& __t,
616 const tuple<_UElements...>& __u)
617 { return !(__t < __u); }
620 template<typename... _Elements>
621 inline tuple<typename __decay_and_strip<_Elements>::__type...>
622 make_tuple(_Elements&&... __args)
624 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
626 return __result_type(std::forward<_Elements>(__args)...);
629 template<typename... _Elements>
630 inline tuple<_Elements&&...>
631 forward_as_tuple(_Elements&&... __args)
632 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
634 template<std::size_t...> struct __index_holder { };
636 template<std::size_t __i, typename _IdxHolder, typename... _Elements>
637 struct __index_holder_impl;
639 template<std::size_t __i, std::size_t... _Indexes, typename _IdxHolder,
640 typename... _Elements>
641 struct __index_holder_impl<__i, __index_holder<_Indexes...>,
642 _IdxHolder, _Elements...>
644 typedef typename __index_holder_impl<__i + 1,
645 __index_holder<_Indexes..., __i>,
646 _Elements...>::type type;
649 template<std::size_t __i, std::size_t... _Indexes>
650 struct __index_holder_impl<__i, __index_holder<_Indexes...> >
651 { typedef __index_holder<_Indexes...> type; };
653 template<typename... _Elements>
654 struct __make_index_holder
655 : __index_holder_impl<0, __index_holder<>, _Elements...> { };
657 template<typename... _TElements, std::size_t... _TIdx,
658 typename... _UElements, std::size_t... _UIdx>
659 inline tuple<_TElements..., _UElements...>
660 __tuple_cat_helper(const tuple<_TElements...>& __t,
661 const __index_holder<_TIdx...>&,
662 const tuple<_UElements...>& __u,
663 const __index_holder<_UIdx...>&)
664 { return tuple<_TElements..., _UElements...>(get<_TIdx>(__t)...,
665 get<_UIdx>(__u)...); }
667 template<typename... _TElements, std::size_t... _TIdx,
668 typename... _UElements, std::size_t... _UIdx>
669 inline tuple<_TElements..., _UElements...>
670 __tuple_cat_helper(tuple<_TElements...>&& __t,
671 const __index_holder<_TIdx...>&,
672 const tuple<_UElements...>& __u,
673 const __index_holder<_UIdx...>&)
674 { return tuple<_TElements..., _UElements...>
675 (std::move(get<_TIdx>(__t))..., get<_UIdx>(__u)...); }
677 template<typename... _TElements, std::size_t... _TIdx,
678 typename... _UElements, std::size_t... _UIdx>
679 inline tuple<_TElements..., _UElements...>
680 __tuple_cat_helper(const tuple<_TElements...>& __t,
681 const __index_holder<_TIdx...>&,
682 tuple<_UElements...>&& __u,
683 const __index_holder<_UIdx...>&)
684 { return tuple<_TElements..., _UElements...>
685 (get<_TIdx>(__t)..., std::move(get<_UIdx>(__u))...); }
687 template<typename... _TElements, std::size_t... _TIdx,
688 typename... _UElements, std::size_t... _UIdx>
689 inline tuple<_TElements..., _UElements...>
690 __tuple_cat_helper(tuple<_TElements...>&& __t,
691 const __index_holder<_TIdx...>&,
692 tuple<_UElements...>&& __u,
693 const __index_holder<_UIdx...>&)
694 { return tuple<_TElements..., _UElements...>
695 (std::move(get<_TIdx>(__t))..., std::move(get<_UIdx>(__u))...); }
697 template<typename... _TElements, typename... _UElements>
698 inline tuple<_TElements..., _UElements...>
699 tuple_cat(const tuple<_TElements...>& __t, const tuple<_UElements...>& __u)
701 return __tuple_cat_helper(__t, typename
702 __make_index_holder<_TElements...>::type(),
704 __make_index_holder<_UElements...>::type());
707 template<typename... _TElements, typename... _UElements>
708 inline tuple<_TElements..., _UElements...>
709 tuple_cat(tuple<_TElements...>&& __t, const tuple<_UElements...>& __u)
711 return __tuple_cat_helper(std::move(__t), typename
712 __make_index_holder<_TElements...>::type(),
714 __make_index_holder<_UElements...>::type());
717 template<typename... _TElements, typename... _UElements>
718 inline tuple<_TElements..., _UElements...>
719 tuple_cat(const tuple<_TElements...>& __t, tuple<_UElements...>&& __u)
721 return __tuple_cat_helper(__t, typename
722 __make_index_holder<_TElements...>::type(),
723 std::move(__u), typename
724 __make_index_holder<_UElements...>::type());
727 template<typename... _TElements, typename... _UElements>
728 inline tuple<_TElements..., _UElements...>
729 tuple_cat(tuple<_TElements...>&& __t, tuple<_UElements...>&& __u)
731 return __tuple_cat_helper(std::move(__t), typename
732 __make_index_holder<_TElements...>::type(),
733 std::move(__u), typename
734 __make_index_holder<_UElements...>::type());
737 template<typename... _Elements>
738 inline tuple<_Elements&...>
739 tie(_Elements&... __args)
740 { return tuple<_Elements&...>(__args...); }
742 template<typename... _Elements>
744 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
747 // A class (and instance) which can be used in 'tie' when an element
748 // of a tuple is not required
749 struct _Swallow_assign
752 const _Swallow_assign&
753 operator=(const _Tp&) const
757 const _Swallow_assign ignore{};
760 * Stores a tuple of indices. Used by bind() to extract the elements
763 template<int... _Indexes>
766 typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next;
769 /// Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
770 template<std::size_t _Num>
771 struct _Build_index_tuple
773 typedef typename _Build_index_tuple<_Num-1>::__type::__next __type;
777 struct _Build_index_tuple<0>
779 typedef _Index_tuple<> __type;
783 template<class _T1, class _T2>
784 template<typename _Tp, typename... _Args>
787 __cons(tuple<_Args...>&& __tuple)
789 typedef typename _Build_index_tuple<sizeof...(_Args)>::__type
791 return __do_cons<_Tp>(std::move(__tuple), _Indexes());
794 template<class _T1, class _T2>
795 template<typename _Tp, typename... _Args, int... _Indexes>
798 __do_cons(tuple<_Args...>&& __tuple,
799 const _Index_tuple<_Indexes...>&)
800 { return _Tp(std::forward<_Args>(get<_Indexes>(__tuple))...); }
802 _GLIBCXX_END_NAMESPACE_VERSION
805 #endif // __GXX_EXPERIMENTAL_CXX0X__
807 #endif // _GLIBCXX_TUPLE