3 // Copyright (C) 2007, 2008 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 2, 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 // You should have received a copy of the GNU General Public License
17 // along with this library; see the file COPYING. If not, write to
18 // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 // Boston, MA 02110-1301, USA.
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
30 /** @file include/tuple
31 * This is a Standard C++ Library header.
34 #ifndef _GLIBCXX_CXX0X_TUPLE
35 #define _GLIBCXX_CXX0X_TUPLE 1
37 #pragma GCC system_header
39 #ifndef __GXX_EXPERIMENTAL_CXX0X__
40 # include <c++0x_warning.h>
47 // Adds a const reference to a non-reference type.
48 template<typename _Tp>
50 { typedef const _Tp& type; };
52 template<typename _Tp>
53 struct __add_c_ref<_Tp&>
54 { typedef _Tp& type; };
56 // Adds a reference to a non-reference type.
57 template<typename _Tp>
59 { typedef _Tp& type; };
61 template<typename _Tp>
62 struct __add_ref<_Tp&>
63 { typedef _Tp& type; };
65 template<int _Idx, typename _Head, bool _IsEmpty>
68 template<int _Idx, typename _Head>
69 struct _Head_base<_Idx, _Head, true>
75 _Head_base(typename __add_c_ref<_Head>::type __h)
78 _Head_base(typename std::remove_reference<_Head>::type&& __h)
79 : _Head(std::forward<_Head>(__h)) { }
81 _Head& _M_head() { return *this; }
82 const _Head& _M_head() const { return *this; }
85 template<int _Idx, typename _Head>
86 struct _Head_base<_Idx, _Head, false>
91 _Head_base(typename __add_c_ref<_Head>::type __h)
92 : _M_head_impl(__h) { }
94 _Head_base(typename std::remove_reference<_Head>::type&& __h)
95 : _M_head_impl(std::move(__h)) { }
97 _Head& _M_head() { return _M_head_impl; }
98 const _Head& _M_head() const { return _M_head_impl; }
104 * Contains the actual implementation of the @c tuple template, stored
105 * as a recursive inheritance hierarchy from the first element (most
106 * derived class) to the last (least derived class). The @c Idx
107 * parameter gives the 0-based index of the element stored at this
108 * point in the hierarchy; we use it to implement a constant-time
111 template<int _Idx, typename... _Elements>
115 * Zero-element tuple implementation. This is the basis case for the
116 * inheritance recursion.
119 struct _Tuple_impl<_Idx> { };
122 * Recursive tuple implementation. Here we store the @c Head element
123 * and derive from a @c Tuple_impl containing the remaining elements
124 * (which contains the @c Tail).
126 template<int _Idx, typename _Head, typename... _Tail>
127 struct _Tuple_impl<_Idx, _Head, _Tail...>
128 : public _Tuple_impl<_Idx + 1, _Tail...>,
129 private _Head_base<_Idx, _Head, std::is_empty<_Head>::value>
131 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
132 typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base;
134 _Head& _M_head() { return _Base::_M_head(); }
135 const _Head& _M_head() const { return _Base::_M_head(); }
137 _Inherited& _M_tail() { return *this; }
138 const _Inherited& _M_tail() const { return *this; }
141 : _Inherited(), _Base() { }
144 _Tuple_impl(typename __add_c_ref<_Head>::type __head,
145 typename __add_c_ref<_Tail>::type... __tail)
146 : _Inherited(__tail...), _Base(__head) { }
148 template<typename _UHead, typename... _UTail>
150 _Tuple_impl(typename std::remove_reference<_UHead>::type&& __head,
151 typename std::remove_reference<_UTail>::type&&... __tail)
152 : _Inherited(std::forward<_Inherited>(__tail)...),
153 _Base(std::forward<_Base>(__head)) { }
155 _Tuple_impl(const _Tuple_impl& __in)
156 : _Inherited(__in._M_tail()), _Base(__in._M_head()) { }
158 _Tuple_impl(_Tuple_impl&& __in)
159 : _Inherited(std::forward<_Inherited>(__in._M_tail())),
160 _Base(std::forward<_Base>(__in._M_head())) { }
162 template<typename... _UElements>
163 _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
164 : _Inherited(__in._M_tail()), _Base(__in._M_head()) { }
166 template<typename... _UElements>
167 _Tuple_impl(_Tuple_impl<_Idx, _UElements...>&& __in)
168 : _Inherited(std::forward<_Inherited>(__in._M_tail())),
169 _Base(std::forward<_Base>(__in._M_head())) { }
172 operator=(const _Tuple_impl& __in)
174 _M_head() = __in._M_head();
175 _M_tail() = __in._M_tail();
180 operator=(_Tuple_impl&& __in)
182 _M_head() = std::move(__in._M_head());
183 _M_tail() = std::move(__in._M_tail());
187 template<typename... _UElements>
189 operator=(const _Tuple_impl<_Idx, _UElements...>& __in)
191 _M_head() = __in._M_head();
192 _M_tail() = __in._M_tail();
196 template<typename... _UElements>
198 operator=(_Tuple_impl<_Idx, _UElements...>&& __in)
200 _M_head() = std::move(__in._M_head());
201 _M_tail() = std::move(__in._M_tail());
206 template<typename... _Elements>
207 class tuple : public _Tuple_impl<0, _Elements...>
209 typedef _Tuple_impl<0, _Elements...> _Inherited;
216 tuple(const _Elements&... __elements)
217 : _Inherited(__elements...) { }
219 template<typename... _UElements>
221 tuple(_UElements&&... __elements)
222 : _Inherited(std::forward<_UElements>(__elements)...) { }
224 tuple(const tuple& __in)
225 : _Inherited(__in) { }
228 : _Inherited(std::move(__in)) { }
230 template<typename... _UElements>
231 tuple(const tuple<_UElements...>& __in)
232 : _Inherited(__in) { }
234 template<typename... _UElements>
235 tuple(tuple<_UElements...>&& __in)
236 : _Inherited(std::move(__in)) { }
239 operator=(const tuple& __in)
241 static_cast<_Inherited&>(*this) = __in;
246 operator=(tuple&& __in)
248 static_cast<_Inherited&>(*this) = std::move(__in);
252 template<typename... _UElements>
254 operator=(const tuple<_UElements...>& __in)
256 static_cast<_Inherited&>(*this) = __in;
260 template<typename... _UElements>
262 operator=(tuple<_UElements...>&& __in)
264 static_cast<_Inherited&>(*this) = std::move(__in);
269 template<> class tuple<> { };
271 // 2-element tuple, with construction and assignment from a pair.
272 template<typename _T1, typename _T2>
273 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
275 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
282 tuple(const _T1& __a1, const _T2& __a2)
283 : _Inherited(__a1, __a2) { }
285 template<typename _U1, typename _U2>
287 tuple(_U1&& __a1, _U2&& __a2)
288 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
290 tuple(const tuple& __in)
291 : _Inherited(__in) { }
294 : _Inherited(std::move(__in)) { }
296 template<typename _U1, typename _U2>
297 tuple(const tuple<_U1, _U2>& __in)
298 : _Inherited(__in) { }
300 template<typename _U1, typename _U2>
301 tuple(tuple<_U1, _U2>&& __in)
302 : _Inherited(std::move(__in)) { }
304 template<typename _U1, typename _U2>
305 tuple(const pair<_U1, _U2>& __in)
306 : _Inherited(_Tuple_impl<0,
307 typename __add_c_ref<_U1>::type,
308 typename __add_c_ref<_U2>::type>(__in.first,
312 template<typename _U1, typename _U2>
313 tuple(pair<_U1, _U2>&& __in)
314 : _Inherited(_Tuple_impl<0,
315 typename std::remove_reference<_U1>::type&&,
316 typename std::remove_reference<_U2>::type&&>
317 (std::move(__in.first), std::move(__in.second)))
321 operator=(const tuple& __in)
323 static_cast<_Inherited&>(*this) = __in;
328 operator=(tuple&& __in)
330 static_cast<_Inherited&>(*this) = std::move(__in);
334 template<typename _U1, typename _U2>
336 operator=(const tuple<_U1, _U2>& __in)
338 static_cast<_Inherited&>(*this) = __in;
342 template<typename _U1, typename _U2>
344 operator=(tuple<_U1, _U2>&& __in)
346 static_cast<_Inherited&>(*this) = std::move(__in);
350 template<typename _U1, typename _U2>
352 operator=(const pair<_U1, _U2>& __in)
354 this->_M_head() = __in.first;
355 this->_M_tail()._M_head() = __in.second;
359 template<typename _U1, typename _U2>
361 operator=(pair<_U1, _U2>&& __in)
363 this->_M_head() = std::move(__in.first);
364 this->_M_tail()._M_head() = std::move(__in.second);
370 /// Gives the type of the ith element of a given tuple type.
371 template<int __i, typename _Tp>
372 struct tuple_element;
375 * Recursive case for tuple_element: strip off the first element in
376 * the tuple and retrieve the (i-1)th element of the remaining tuple.
378 template<int __i, typename _Head, typename... _Tail>
379 struct tuple_element<__i, tuple<_Head, _Tail...> >
380 : tuple_element<__i - 1, tuple<_Tail...> > { };
383 * Basis case for tuple_element: The first element is the one we're seeking.
385 template<typename _Head, typename... _Tail>
386 struct tuple_element<0, tuple<_Head, _Tail...> >
391 /// Finds the size of a given tuple type.
392 template<typename _Tp>
395 /// @brief class tuple_size
396 template<typename... _Elements>
397 struct tuple_size<tuple<_Elements...> >
399 static const int value = sizeof...(_Elements);
402 template<typename... _Elements>
403 const int tuple_size<tuple<_Elements...> >::value;
405 template<int __i, typename _Head, typename... _Tail>
406 inline typename __add_ref<_Head>::type
407 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t)
408 { return __t._M_head(); }
410 template<int __i, typename _Head, typename... _Tail>
411 inline typename __add_c_ref<_Head>::type
412 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t)
413 { return __t._M_head(); }
415 // Return a reference (const reference) to the ith element of a tuple.
416 // Any const or non-const ref elements are returned with their original type.
417 template<int __i, typename... _Elements>
418 inline typename __add_ref<
419 typename tuple_element<__i, tuple<_Elements...> >::type
421 get(tuple<_Elements...>& __t)
422 { return __get_helper<__i>(__t); }
424 template<int __i, typename... _Elements>
425 inline typename __add_c_ref<
426 typename tuple_element<__i, tuple<_Elements...> >::type
428 get(const tuple<_Elements...>& __t)
429 { return __get_helper<__i>(__t); }
431 // This class helps construct the various comparison operations on tuples
432 template<int __check_equal_size, int __i, int __j,
433 typename _Tp, typename _Up>
434 struct __tuple_compare;
436 template<int __i, int __j, typename _Tp, typename _Up>
437 struct __tuple_compare<0, __i, __j, _Tp, _Up>
439 static bool __eq(const _Tp& __t, const _Up& __u)
441 return (get<__i>(__t) == get<__i>(__u) &&
442 __tuple_compare<0, __i+1, __j, _Tp, _Up>::__eq(__t, __u));
445 static bool __less(const _Tp& __t, const _Up& __u)
447 return ((get<__i>(__t) < get<__i>(__u))
448 || !(get<__i>(__u) < get<__i>(__t)) &&
449 __tuple_compare<0, __i+1, __j, _Tp, _Up>::__less(__t, __u));
453 template<int __i, typename _Tp, typename _Up>
454 struct __tuple_compare<0, __i, __i, _Tp, _Up>
456 static bool __eq(const _Tp&, const _Up&)
459 static bool __less(const _Tp&, const _Up&)
463 template<typename... _TElements, typename... _UElements>
465 operator==(const tuple<_TElements...>& __t,
466 const tuple<_UElements...>& __u)
468 typedef tuple<_TElements...> _Tp;
469 typedef tuple<_UElements...> _Up;
470 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Tp>::value,
471 0, tuple_size<_Tp>::value, _Tp, _Up>::__eq(__t, __u));
474 template<typename... _TElements, typename... _UElements>
476 operator<(const tuple<_TElements...>& __t,
477 const tuple<_UElements...>& __u)
479 typedef tuple<_TElements...> _Tp;
480 typedef tuple<_UElements...> _Up;
481 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Tp>::value,
482 0, tuple_size<_Tp>::value, _Tp, _Up>::__less(__t, __u));
485 template<typename... _TElements, typename... _UElements>
487 operator!=(const tuple<_TElements...>& __t,
488 const tuple<_UElements...>& __u)
489 { return !(__t == __u); }
491 template<typename... _TElements, typename... _UElements>
493 operator>(const tuple<_TElements...>& __t,
494 const tuple<_UElements...>& __u)
495 { return __u < __t; }
497 template<typename... _TElements, typename... _UElements>
499 operator<=(const tuple<_TElements...>& __t,
500 const tuple<_UElements...>& __u)
501 { return !(__u < __t); }
503 template<typename... _TElements, typename... _UElements>
505 operator>=(const tuple<_TElements...>& __t,
506 const tuple<_UElements...>& __u)
507 { return !(__t < __u); }
510 template<typename... _Elements>
511 inline tuple<typename __decay_and_strip<_Elements>::__type...>
512 make_tuple(_Elements&&... __args)
514 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
516 return __result_type(std::forward<_Elements>(__args)...);
519 template<int...> struct __index_holder { };
521 template<int __i, typename _IdxHolder, typename... _Elements>
522 struct __index_holder_impl;
524 template<int __i, int... _Indexes, typename _IdxHolder, typename... _Elements>
525 struct __index_holder_impl<__i, __index_holder<_Indexes...>,
526 _IdxHolder, _Elements...>
528 typedef typename __index_holder_impl<__i + 1,
529 __index_holder<_Indexes..., __i>,
530 _Elements...>::type type;
533 template<int __i, int... _Indexes>
534 struct __index_holder_impl<__i, __index_holder<_Indexes...> >
535 { typedef __index_holder<_Indexes...> type; };
537 template<typename... _Elements>
538 struct __make_index_holder
539 : __index_holder_impl<0, __index_holder<>, _Elements...> { };
541 template<typename... _TElements, int... _TIdx,
542 typename... _UElements, int... _UIdx>
543 inline tuple<_TElements..., _UElements...>
544 __tuple_cat_helper(const tuple<_TElements...>& __t,
545 const __index_holder<_TIdx...>&,
546 const tuple<_UElements...>& __u,
547 const __index_holder<_UIdx...>&)
548 { return tuple<_TElements..., _UElements...>(get<_TIdx>(__t)...,
549 get<_UIdx>(__u)...); }
551 template<typename... _TElements, int... _TIdx,
552 typename... _UElements, int... _UIdx>
553 inline tuple<_TElements..., _UElements...>
554 __tuple_cat_helper(tuple<_TElements...>&& __t,
555 const __index_holder<_TIdx...>&,
556 const tuple<_UElements...>& __u,
557 const __index_holder<_UIdx...>&)
558 { return tuple<_TElements..., _UElements...>(std::move(get<_TIdx>(__t))...,
559 get<_UIdx>(__u)...); }
561 template<typename... _TElements, int... _TIdx,
562 typename... _UElements, int... _UIdx>
563 inline tuple<_TElements..., _UElements...>
564 __tuple_cat_helper(const tuple<_TElements...>& __t,
565 const __index_holder<_TIdx...>&,
566 tuple<_UElements...>&& __u,
567 const __index_holder<_UIdx...>&)
568 { return tuple<_TElements..., _UElements...>(get<_TIdx>(__t)...,
569 std::move(get<_UIdx>(__u))...); }
571 template<typename... _TElements, int... _TIdx,
572 typename... _UElements, int... _UIdx>
573 inline tuple<_TElements..., _UElements...>
574 __tuple_cat_helper(tuple<_TElements...>&& __t,
575 const __index_holder<_TIdx...>&,
576 tuple<_UElements...>&& __u,
577 const __index_holder<_UIdx...>&)
578 { return tuple<_TElements..., _UElements...>(std::move(get<_TIdx>(__t))...,
579 std::move(get<_UIdx>(__u))...); }
581 template<typename... _TElements, typename... _UElements>
582 inline tuple<_TElements..., _UElements...>
583 tuple_cat(const tuple<_TElements...>& __t, const tuple<_UElements...>& __u)
585 return __tuple_cat_helper(__t, typename
586 __make_index_holder<_TElements...>::type(),
588 __make_index_holder<_UElements...>::type());
591 template<typename... _TElements, typename... _UElements>
592 inline tuple<_TElements..., _UElements...>
593 tuple_cat(tuple<_TElements...>&& __t, const tuple<_UElements...>& __u)
595 return __tuple_cat_helper(std::move(__t), typename
596 __make_index_holder<_TElements...>::type(),
598 __make_index_holder<_UElements...>::type());
601 template<typename... _TElements, typename... _UElements>
602 inline tuple<_TElements..., _UElements...>
603 tuple_cat(const tuple<_TElements...>& __t, tuple<_UElements...>&& __u)
605 return __tuple_cat_helper(__t, typename
606 __make_index_holder<_TElements...>::type(),
607 std::move(__u), typename
608 __make_index_holder<_UElements...>::type());
611 template<typename... _TElements, typename... _UElements>
612 inline tuple<_TElements..., _UElements...>
613 tuple_cat(tuple<_TElements...>&& __t, tuple<_UElements...>&& __u)
615 return __tuple_cat_helper(std::move(__t), typename
616 __make_index_holder<_TElements...>::type(),
617 std::move(__u), typename
618 __make_index_holder<_UElements...>::type());
621 template<typename... _TElements, typename... _UElements>
622 tuple<_TElements..., _UElements...>
623 operator+(tuple<_TElements...>&& __t, tuple<_UElements...>&& __u)
624 { return tuple_cat(std::forward<decltype(__t)>(__t),
625 std::forward<decltype(__u)>(__u)); }
627 template<typename... _Elements>
628 inline tuple<_Elements&...>
629 tie(_Elements&... __args)
630 { return tuple<_Elements&...>(__args...); }
632 // A class (and instance) which can be used in 'tie' when an element
633 // of a tuple is not required
634 struct _Swallow_assign
638 operator=(const _Tp&)
642 // TODO: Put this in some kind of shared file.
645 _Swallow_assign ignore;
646 }; // anonymous namespace
649 #endif // _GLIBCXX_CXX0X_TUPLE