3 // Copyright (C) 2007, 2008, 2009, 2010, 2011 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>
39 #include <bits/uses_allocator.h>
41 namespace std _GLIBCXX_VISIBILITY(default)
43 _GLIBCXX_BEGIN_NAMESPACE_VERSION
45 // Adds a const reference to a non-reference type.
46 template<typename _Tp>
48 { typedef const _Tp& type; };
50 template<typename _Tp>
51 struct __add_c_ref<_Tp&>
52 { typedef _Tp& type; };
54 // Adds a reference to a non-reference type.
55 template<typename _Tp>
57 { typedef _Tp& type; };
59 template<typename _Tp>
60 struct __add_ref<_Tp&>
61 { typedef _Tp& type; };
63 // Adds an rvalue reference to a non-reference type.
64 template<typename _Tp>
66 { typedef _Tp&& type; };
68 template<typename _Tp>
69 struct __add_r_ref<_Tp&>
70 { typedef _Tp& type; };
72 template<std::size_t _Idx, typename _Head, bool _IsEmpty>
75 template<std::size_t _Idx, typename _Head>
76 struct _Head_base<_Idx, _Head, true>
79 constexpr _Head_base()
82 constexpr _Head_base(const _Head& __h)
85 template<typename _UHead, typename = typename
86 enable_if<!is_convertible<_UHead,
87 __uses_alloc_base>::value>::type>
88 constexpr _Head_base(_UHead&& __h)
89 : _Head(std::forward<_UHead>(__h)) { }
91 _Head_base(__uses_alloc0)
94 template<typename _Alloc>
95 _Head_base(__uses_alloc1<_Alloc> __a)
96 : _Head(allocator_arg, *__a._M_a) { }
98 template<typename _Alloc>
99 _Head_base(__uses_alloc2<_Alloc> __a)
100 : _Head(*__a._M_a) { }
102 template<typename _UHead>
103 _Head_base(__uses_alloc0, _UHead&& __uhead)
104 : _Head(std::forward<_UHead>(__uhead)) { }
106 template<typename _Alloc, typename _UHead>
107 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
108 : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
110 template<typename _Alloc, typename _UHead>
111 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
112 : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
114 static constexpr _Head&
115 _M_head(_Head_base& __b) noexcept { return __b; }
117 static constexpr const _Head&
118 _M_head(const _Head_base& __b) noexcept { return __b; }
121 template<std::size_t _Idx, typename _Head>
122 struct _Head_base<_Idx, _Head, false>
124 constexpr _Head_base()
127 constexpr _Head_base(const _Head& __h)
128 : _M_head_impl(__h) { }
130 template<typename _UHead, typename = typename
131 enable_if<!is_convertible<_UHead,
132 __uses_alloc_base>::value>::type>
133 constexpr _Head_base(_UHead&& __h)
134 : _M_head_impl(std::forward<_UHead>(__h)) { }
136 _Head_base(__uses_alloc0)
139 template<typename _Alloc>
140 _Head_base(__uses_alloc1<_Alloc> __a)
141 : _M_head_impl(allocator_arg, *__a._M_a) { }
143 template<typename _Alloc>
144 _Head_base(__uses_alloc2<_Alloc> __a)
145 : _M_head_impl(*__a._M_a) { }
147 template<typename _UHead>
148 _Head_base(__uses_alloc0, _UHead&& __uhead)
149 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
151 template<typename _Alloc, typename _UHead>
152 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
153 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
156 template<typename _Alloc, typename _UHead>
157 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
158 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
160 static constexpr _Head&
161 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
163 static constexpr const _Head&
164 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
170 * Contains the actual implementation of the @c tuple template, stored
171 * as a recursive inheritance hierarchy from the first element (most
172 * derived class) to the last (least derived class). The @c Idx
173 * parameter gives the 0-based index of the element stored at this
174 * point in the hierarchy; we use it to implement a constant-time
177 template<std::size_t _Idx, typename... _Elements>
181 * Zero-element tuple implementation. This is the basis case for the
182 * inheritance recursion.
184 template<std::size_t _Idx>
185 struct _Tuple_impl<_Idx>
187 template<std::size_t, typename...> friend class _Tuple_impl;
189 _Tuple_impl() = default;
191 template<typename _Alloc>
192 _Tuple_impl(allocator_arg_t, const _Alloc&) { }
194 template<typename _Alloc>
195 _Tuple_impl(allocator_arg_t, const _Alloc&, const _Tuple_impl&) { }
197 template<typename _Alloc>
198 _Tuple_impl(allocator_arg_t, const _Alloc&, _Tuple_impl&&) { }
201 void _M_swap(_Tuple_impl&) noexcept { /* no-op */ }
205 * Recursive tuple implementation. Here we store the @c Head element
206 * and derive from a @c Tuple_impl containing the remaining elements
207 * (which contains the @c Tail).
209 template<std::size_t _Idx, typename _Head, typename... _Tail>
210 struct _Tuple_impl<_Idx, _Head, _Tail...>
211 : public _Tuple_impl<_Idx + 1, _Tail...>,
212 private _Head_base<_Idx, _Head, std::is_empty<_Head>::value>
214 template<std::size_t, typename...> friend class _Tuple_impl;
216 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
217 typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base;
219 static constexpr _Head&
220 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
222 static constexpr const _Head&
223 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
225 static constexpr _Inherited&
226 _M_tail(_Tuple_impl& __t) noexcept { return __t; }
228 static constexpr const _Inherited&
229 _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
231 constexpr _Tuple_impl()
232 : _Inherited(), _Base() { }
235 constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail)
236 : _Inherited(__tail...), _Base(__head) { }
238 template<typename _UHead, typename... _UTail, typename = typename
239 enable_if<sizeof...(_Tail) == sizeof...(_UTail)>::type>
241 constexpr _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
242 : _Inherited(std::forward<_UTail>(__tail)...),
243 _Base(std::forward<_UHead>(__head)) { }
245 constexpr _Tuple_impl(const _Tuple_impl&) = default;
248 _Tuple_impl(_Tuple_impl&& __in)
249 noexcept(__and_<is_nothrow_move_constructible<_Head>,
250 is_nothrow_move_constructible<_Inherited>>::value)
251 : _Inherited(std::move(_M_tail(__in))),
252 _Base(std::forward<_Head>(_M_head(__in))) { }
254 template<typename... _UElements>
255 constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
256 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
257 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { }
259 template<typename _UHead, typename... _UTails>
260 constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
261 : _Inherited(std::move
262 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
263 _Base(std::forward<_UHead>
264 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { }
266 template<typename _Alloc>
267 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
268 : _Inherited(__tag, __a),
269 _Base(__use_alloc<_Head>(__a)) { }
271 template<typename _Alloc>
272 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
273 const _Head& __head, const _Tail&... __tail)
274 : _Inherited(__tag, __a, __tail...),
275 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { }
277 template<typename _Alloc, typename _UHead, typename... _UTail,
278 typename = typename enable_if<sizeof...(_Tail)
279 == sizeof...(_UTail)>::type>
280 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
281 _UHead&& __head, _UTail&&... __tail)
282 : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
283 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
284 std::forward<_UHead>(__head)) { }
286 template<typename _Alloc>
287 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
288 const _Tuple_impl& __in)
289 : _Inherited(__tag, __a, _M_tail(__in)),
290 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { }
292 template<typename _Alloc>
293 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
295 : _Inherited(__tag, __a, std::move(_M_tail(__in))),
296 _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
297 std::forward<_Head>(_M_head(__in))) { }
299 template<typename _Alloc, typename... _UElements>
300 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
301 const _Tuple_impl<_Idx, _UElements...>& __in)
302 : _Inherited(__tag, __a,
303 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
304 _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
305 _Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { }
307 template<typename _Alloc, typename _UHead, typename... _UTails>
308 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
309 _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
310 : _Inherited(__tag, __a, std::move
311 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
312 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
314 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { }
317 operator=(const _Tuple_impl& __in)
319 _M_head(*this) = _M_head(__in);
320 _M_tail(*this) = _M_tail(__in);
325 operator=(_Tuple_impl&& __in)
326 noexcept(__and_<is_nothrow_move_assignable<_Head>,
327 is_nothrow_move_assignable<_Inherited>>::value)
329 _M_head(*this) = std::forward<_Head>(_M_head(__in));
330 _M_tail(*this) = std::move(_M_tail(__in));
334 template<typename... _UElements>
336 operator=(const _Tuple_impl<_Idx, _UElements...>& __in)
338 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
339 _M_tail(*this) = _Tuple_impl<_Idx, _UElements...>::_M_tail(__in);
343 template<typename _UHead, typename... _UTails>
345 operator=(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
347 _M_head(*this) = std::forward<_UHead>
348 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
349 _M_tail(*this) = std::move
350 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in));
356 _M_swap(_Tuple_impl& __in)
357 noexcept(noexcept(swap(std::declval<_Head&>(),
358 std::declval<_Head&>()))
359 && noexcept(_M_tail(__in)._M_swap(_M_tail(__in))))
362 swap(_M_head(*this), _M_head(__in));
363 _Inherited::_M_swap(_M_tail(__in));
367 /// Primary class template, tuple
368 template<typename... _Elements>
369 class tuple : public _Tuple_impl<0, _Elements...>
371 typedef _Tuple_impl<0, _Elements...> _Inherited;
378 constexpr tuple(const _Elements&... __elements)
379 : _Inherited(__elements...) { }
381 template<typename... _UElements, typename = typename
382 enable_if<__and_<is_convertible<_UElements,
383 _Elements>...>::value>::type>
385 constexpr tuple(_UElements&&... __elements)
386 : _Inherited(std::forward<_UElements>(__elements)...) { }
388 constexpr tuple(const tuple&) = default;
390 constexpr tuple(tuple&&) = default;
392 template<typename... _UElements, typename = typename
393 enable_if<__and_<is_convertible<const _UElements&,
394 _Elements>...>::value>::type>
395 constexpr tuple(const tuple<_UElements...>& __in)
396 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
399 template<typename... _UElements, typename = typename
400 enable_if<__and_<is_convertible<_UElements,
401 _Elements>...>::value>::type>
402 constexpr tuple(tuple<_UElements...>&& __in)
403 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
405 // Allocator-extended constructors.
407 template<typename _Alloc>
408 tuple(allocator_arg_t __tag, const _Alloc& __a)
409 : _Inherited(__tag, __a) { }
411 template<typename _Alloc>
412 tuple(allocator_arg_t __tag, const _Alloc& __a,
413 const _Elements&... __elements)
414 : _Inherited(__tag, __a, __elements...) { }
416 template<typename _Alloc, typename... _UElements, typename = typename
417 enable_if<sizeof...(_UElements)
418 == sizeof...(_Elements)>::type>
419 tuple(allocator_arg_t __tag, const _Alloc& __a,
420 _UElements&&... __elements)
421 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
424 template<typename _Alloc>
425 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
426 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
428 template<typename _Alloc>
429 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
430 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
432 template<typename _Alloc, typename... _UElements, typename = typename
433 enable_if<sizeof...(_UElements)
434 == sizeof...(_Elements)>::type>
435 tuple(allocator_arg_t __tag, const _Alloc& __a,
436 const tuple<_UElements...>& __in)
437 : _Inherited(__tag, __a,
438 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
441 template<typename _Alloc, typename... _UElements, typename = typename
442 enable_if<sizeof...(_UElements)
443 == sizeof...(_Elements)>::type>
444 tuple(allocator_arg_t __tag, const _Alloc& __a,
445 tuple<_UElements...>&& __in)
446 : _Inherited(__tag, __a,
447 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
451 operator=(const tuple& __in)
453 static_cast<_Inherited&>(*this) = __in;
458 operator=(tuple&& __in)
459 noexcept(is_nothrow_move_assignable<_Inherited>::value)
461 static_cast<_Inherited&>(*this) = std::move(__in);
465 template<typename... _UElements, typename = typename
466 enable_if<sizeof...(_UElements)
467 == sizeof...(_Elements)>::type>
469 operator=(const tuple<_UElements...>& __in)
471 static_cast<_Inherited&>(*this) = __in;
475 template<typename... _UElements, typename = typename
476 enable_if<sizeof...(_UElements)
477 == sizeof...(_Elements)>::type>
479 operator=(tuple<_UElements...>&& __in)
481 static_cast<_Inherited&>(*this) = std::move(__in);
487 noexcept(noexcept(__in._M_swap(__in)))
488 { _Inherited::_M_swap(__in); }
491 // Explicit specialization, zero-element tuple.
496 void swap(tuple&) noexcept { /* no-op */ }
499 /// Partial specialization, 2-element tuple.
500 /// Includes construction and assignment from a pair.
501 template<typename _T1, typename _T2>
502 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
504 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
511 constexpr tuple(const _T1& __a1, const _T2& __a2)
512 : _Inherited(__a1, __a2) { }
514 template<typename _U1, typename _U2, typename = typename
515 enable_if<__and_<is_convertible<_U1, _T1>,
516 is_convertible<_U2, _T2>>::value>::type>
518 constexpr tuple(_U1&& __a1, _U2&& __a2)
519 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
521 constexpr tuple(const tuple&) = default;
523 constexpr tuple(tuple&&) = default;
525 template<typename _U1, typename _U2, typename = typename
526 enable_if<__and_<is_convertible<const _U1&, _T1>,
527 is_convertible<const _U2&, _T2>>::value>::type>
528 constexpr tuple(const tuple<_U1, _U2>& __in)
529 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
531 template<typename _U1, typename _U2, typename = typename
532 enable_if<__and_<is_convertible<_U1, _T1>,
533 is_convertible<_U2, _T2>>::value>::type>
534 constexpr tuple(tuple<_U1, _U2>&& __in)
535 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
537 template<typename _U1, typename _U2, typename = typename
538 enable_if<__and_<is_convertible<const _U1&, _T1>,
539 is_convertible<const _U2&, _T2>>::value>::type>
540 constexpr tuple(const pair<_U1, _U2>& __in)
541 : _Inherited(__in.first, __in.second) { }
543 template<typename _U1, typename _U2, typename = typename
544 enable_if<__and_<is_convertible<_U1, _T1>,
545 is_convertible<_U2, _T2>>::value>::type>
546 constexpr tuple(pair<_U1, _U2>&& __in)
547 : _Inherited(std::forward<_U1>(__in.first),
548 std::forward<_U2>(__in.second)) { }
550 // Allocator-extended constructors.
552 template<typename _Alloc>
553 tuple(allocator_arg_t __tag, const _Alloc& __a)
554 : _Inherited(__tag, __a) { }
556 template<typename _Alloc>
557 tuple(allocator_arg_t __tag, const _Alloc& __a,
558 const _T1& __a1, const _T2& __a2)
559 : _Inherited(__tag, __a, __a1, __a2) { }
561 template<typename _Alloc, typename _U1, typename _U2>
562 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
563 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
564 std::forward<_U2>(__a2)) { }
566 template<typename _Alloc>
567 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
568 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
570 template<typename _Alloc>
571 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
572 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
574 template<typename _Alloc, typename _U1, typename _U2>
575 tuple(allocator_arg_t __tag, const _Alloc& __a,
576 const tuple<_U1, _U2>& __in)
577 : _Inherited(__tag, __a,
578 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
581 template<typename _Alloc, typename _U1, typename _U2>
582 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
583 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
586 template<typename _Alloc, typename _U1, typename _U2>
587 tuple(allocator_arg_t __tag, const _Alloc& __a,
588 const pair<_U1, _U2>& __in)
589 : _Inherited(__tag, __a, __in.first, __in.second) { }
591 template<typename _Alloc, typename _U1, typename _U2>
592 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
593 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
594 std::forward<_U2>(__in.second)) { }
597 operator=(const tuple& __in)
599 static_cast<_Inherited&>(*this) = __in;
604 operator=(tuple&& __in)
605 noexcept(is_nothrow_move_assignable<_Inherited>::value)
607 static_cast<_Inherited&>(*this) = std::move(__in);
611 template<typename _U1, typename _U2>
613 operator=(const tuple<_U1, _U2>& __in)
615 static_cast<_Inherited&>(*this) = __in;
619 template<typename _U1, typename _U2>
621 operator=(tuple<_U1, _U2>&& __in)
623 static_cast<_Inherited&>(*this) = std::move(__in);
627 template<typename _U1, typename _U2>
629 operator=(const pair<_U1, _U2>& __in)
631 this->_M_head(*this) = __in.first;
632 this->_M_tail(*this)._M_head(*this) = __in.second;
636 template<typename _U1, typename _U2>
638 operator=(pair<_U1, _U2>&& __in)
640 this->_M_head(*this) = std::forward<_U1>(__in.first);
641 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
647 noexcept(noexcept(__in._M_swap(__in)))
648 { _Inherited::_M_swap(__in); }
652 /// Gives the type of the ith element of a given tuple type.
653 template<std::size_t __i, typename _Tp>
654 struct tuple_element;
657 * Recursive case for tuple_element: strip off the first element in
658 * the tuple and retrieve the (i-1)th element of the remaining tuple.
660 template<std::size_t __i, typename _Head, typename... _Tail>
661 struct tuple_element<__i, tuple<_Head, _Tail...> >
662 : tuple_element<__i - 1, tuple<_Tail...> > { };
665 * Basis case for tuple_element: The first element is the one we're seeking.
667 template<typename _Head, typename... _Tail>
668 struct tuple_element<0, tuple<_Head, _Tail...> >
673 template<std::size_t __i, typename _Tp>
674 struct tuple_element<__i, const _Tp>
677 add_const<typename tuple_element<__i, _Tp>::type>::type type;
680 template<std::size_t __i, typename _Tp>
681 struct tuple_element<__i, volatile _Tp>
684 add_volatile<typename tuple_element<__i, _Tp>::type>::type type;
687 template<std::size_t __i, typename _Tp>
688 struct tuple_element<__i, const volatile _Tp>
691 add_cv<typename tuple_element<__i, _Tp>::type>::type type;
694 /// Finds the size of a given tuple type.
695 template<typename _Tp>
698 template<typename _Tp>
699 struct tuple_size<const _Tp>
700 : public integral_constant<
701 typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
702 tuple_size<_Tp>::value> { };
704 template<typename _Tp>
705 struct tuple_size<volatile _Tp>
706 : public integral_constant<
707 typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
708 tuple_size<_Tp>::value> { };
710 template<typename _Tp>
711 struct tuple_size<const volatile _Tp>
712 : public integral_constant<
713 typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
714 tuple_size<_Tp>::value> { };
717 template<typename... _Elements>
718 struct tuple_size<tuple<_Elements...>>
719 : public integral_constant<std::size_t, sizeof...(_Elements)> { };
721 template<std::size_t __i, typename _Head, typename... _Tail>
722 constexpr typename __add_ref<_Head>::type
723 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
724 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
726 template<std::size_t __i, typename _Head, typename... _Tail>
727 constexpr typename __add_c_ref<_Head>::type
728 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
729 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
731 // Return a reference (const reference, rvalue reference) to the ith element
732 // of a tuple. Any const or non-const ref elements are returned with their
734 template<std::size_t __i, typename... _Elements>
735 constexpr typename __add_ref<
736 typename tuple_element<__i, tuple<_Elements...>>::type
738 get(tuple<_Elements...>& __t) noexcept
739 { return __get_helper<__i>(__t); }
741 template<std::size_t __i, typename... _Elements>
742 constexpr typename __add_c_ref<
743 typename tuple_element<__i, tuple<_Elements...>>::type
745 get(const tuple<_Elements...>& __t) noexcept
746 { return __get_helper<__i>(__t); }
748 template<std::size_t __i, typename... _Elements>
749 constexpr typename __add_r_ref<
750 typename tuple_element<__i, tuple<_Elements...>>::type
752 get(tuple<_Elements...>&& __t) noexcept
753 { return std::forward<typename tuple_element<__i,
754 tuple<_Elements...>>::type&&>(get<__i>(__t)); }
756 // This class helps construct the various comparison operations on tuples
757 template<std::size_t __check_equal_size, std::size_t __i, std::size_t __j,
758 typename _Tp, typename _Up>
759 struct __tuple_compare;
761 template<std::size_t __i, std::size_t __j, typename _Tp, typename _Up>
762 struct __tuple_compare<0, __i, __j, _Tp, _Up>
765 __eq(const _Tp& __t, const _Up& __u)
767 return (get<__i>(__t) == get<__i>(__u) &&
768 __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__eq(__t, __u));
772 __less(const _Tp& __t, const _Up& __u)
774 return ((get<__i>(__t) < get<__i>(__u))
775 || !(get<__i>(__u) < get<__i>(__t)) &&
776 __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__less(__t, __u));
780 template<std::size_t __i, typename _Tp, typename _Up>
781 struct __tuple_compare<0, __i, __i, _Tp, _Up>
784 __eq(const _Tp&, const _Up&) { return true; }
787 __less(const _Tp&, const _Up&) { return false; }
790 template<typename... _TElements, typename... _UElements>
792 operator==(const tuple<_TElements...>& __t,
793 const tuple<_UElements...>& __u)
795 typedef tuple<_TElements...> _Tp;
796 typedef tuple<_UElements...> _Up;
797 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value,
798 0, tuple_size<_Tp>::value, _Tp, _Up>::__eq(__t, __u));
801 template<typename... _TElements, typename... _UElements>
803 operator<(const tuple<_TElements...>& __t,
804 const tuple<_UElements...>& __u)
806 typedef tuple<_TElements...> _Tp;
807 typedef tuple<_UElements...> _Up;
808 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value,
809 0, tuple_size<_Tp>::value, _Tp, _Up>::__less(__t, __u));
812 template<typename... _TElements, typename... _UElements>
814 operator!=(const tuple<_TElements...>& __t,
815 const tuple<_UElements...>& __u)
816 { return !(__t == __u); }
818 template<typename... _TElements, typename... _UElements>
820 operator>(const tuple<_TElements...>& __t,
821 const tuple<_UElements...>& __u)
822 { return __u < __t; }
824 template<typename... _TElements, typename... _UElements>
826 operator<=(const tuple<_TElements...>& __t,
827 const tuple<_UElements...>& __u)
828 { return !(__u < __t); }
830 template<typename... _TElements, typename... _UElements>
832 operator>=(const tuple<_TElements...>& __t,
833 const tuple<_UElements...>& __u)
834 { return !(__t < __u); }
837 template<typename... _Elements>
838 constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
839 make_tuple(_Elements&&... __args)
841 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
843 return __result_type(std::forward<_Elements>(__args)...);
846 template<typename... _Elements>
847 constexpr tuple<_Elements&&...>
848 forward_as_tuple(_Elements&&... __args) noexcept
849 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
852 template<typename, std::size_t> struct array;
854 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
855 constexpr _Tp& get(array<_Tp, _Nm>&) noexcept;
857 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
858 constexpr _Tp&& get(array<_Tp, _Nm>&&) noexcept;
860 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
861 constexpr const _Tp& get(const array<_Tp, _Nm>&) noexcept;
864 struct __is_tuple_like_impl : false_type
867 template<typename... _Tps>
868 struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
871 template<typename _T1, typename _T2>
872 struct __is_tuple_like_impl<pair<_T1, _T2>> : true_type
875 template<typename _Tp, std::size_t _Nm>
876 struct __is_tuple_like_impl<array<_Tp, _Nm>> : true_type
879 // Internal type trait that allows us to sfinae-protect tuple_cat.
880 template<typename _Tp>
881 struct __is_tuple_like
882 : public __is_tuple_like_impl<typename std::remove_cv
883 <typename std::remove_reference<_Tp>::type>::type>::type
886 // Stores a tuple of indices. Also used by bind() to extract the elements
888 template<std::size_t... _Indexes>
891 typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next;
894 // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
895 template<std::size_t _Num>
896 struct _Build_index_tuple
898 typedef typename _Build_index_tuple<_Num - 1>::__type::__next __type;
902 struct _Build_index_tuple<0>
904 typedef _Index_tuple<> __type;
907 template<std::size_t, typename, typename, std::size_t>
908 struct __make_tuple_impl;
910 template<std::size_t _Idx, typename _Tuple, typename... _Tp,
912 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
914 typedef typename __make_tuple_impl<_Idx + 1, tuple<_Tp...,
915 typename std::tuple_element<_Idx, _Tuple>::type>, _Tuple, _Nm>::__type
919 template<std::size_t _Nm, typename _Tuple, typename... _Tp>
920 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
922 typedef tuple<_Tp...> __type;
925 template<typename _Tuple>
926 struct __do_make_tuple
927 : public __make_tuple_impl<0, tuple<>, _Tuple,
928 std::tuple_size<_Tuple>::value>
931 // Returns the std::tuple equivalent of a tuple-like type.
932 template<typename _Tuple>
934 : public __do_make_tuple<typename std::remove_cv
935 <typename std::remove_reference<_Tuple>::type>::type>
938 // Combines several std::tuple's into a single one.
939 template<typename...>
940 struct __combine_tuples;
943 struct __combine_tuples<>
945 typedef tuple<> __type;
948 template<typename... _Ts>
949 struct __combine_tuples<tuple<_Ts...>>
951 typedef tuple<_Ts...> __type;
954 template<typename... _T1s, typename... _T2s, typename... _Rem>
955 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
957 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
958 _Rem...>::__type __type;
961 // Computes the result type of tuple_cat given a set of tuple-like types.
962 template<typename... _Tpls>
963 struct __tuple_cat_result
965 typedef typename __combine_tuples
966 <typename __make_tuple<_Tpls>::__type...>::__type __type;
969 // Helper to determine the index set for the first tuple-like
970 // type of a given set.
971 template<typename...>
972 struct __make_1st_indices;
975 struct __make_1st_indices<>
977 typedef std::_Index_tuple<> __type;
980 template<typename _Tp, typename... _Tpls>
981 struct __make_1st_indices<_Tp, _Tpls...>
983 typedef typename std::_Build_index_tuple<std::tuple_size<
984 typename std::remove_reference<_Tp>::type>::value>::__type __type;
987 // Performs the actual concatenation by step-wise expanding tuple-like
988 // objects into the elements, which are finally forwarded into the
990 template<typename _Ret, typename _Indices, typename... _Tpls>
991 struct __tuple_concater;
993 template<typename _Ret, std::size_t... _Is, typename _Tp, typename... _Tpls>
994 struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...>
996 template<typename... _Us>
997 static constexpr _Ret
998 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
1000 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
1001 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
1002 return __next::_S_do(std::forward<_Tpls>(__tps)...,
1003 std::forward<_Us>(__us)...,
1004 std::get<_Is>(std::forward<_Tp>(__tp))...);
1008 template<typename _Ret>
1009 struct __tuple_concater<_Ret, std::_Index_tuple<>>
1011 template<typename... _Us>
1012 static constexpr _Ret
1013 _S_do(_Us&&... __us)
1015 return _Ret(std::forward<_Us>(__us)...);
1019 template<typename... _Tpls, typename = typename
1020 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
1022 tuple_cat(_Tpls&&... __tpls)
1023 -> typename __tuple_cat_result<_Tpls...>::__type
1025 typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
1026 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
1027 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
1028 return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
1031 template<typename... _Elements>
1032 inline tuple<_Elements&...>
1033 tie(_Elements&... __args) noexcept
1034 { return tuple<_Elements&...>(__args...); }
1036 template<typename... _Elements>
1038 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
1039 noexcept(noexcept(__x.swap(__y)))
1042 // A class (and instance) which can be used in 'tie' when an element
1043 // of a tuple is not required
1044 struct _Swallow_assign
1047 const _Swallow_assign&
1048 operator=(const _Tp&) const
1052 const _Swallow_assign ignore{};
1054 /// Partial specialization for tuples
1055 template<typename... _Types, typename _Alloc>
1056 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
1058 // See stl_pair.h...
1059 template<class _T1, class _T2>
1060 template<typename _Tp, typename... _Args>
1062 pair<_T1, _T2>::__cons(tuple<_Args...>&& __tuple)
1064 typedef typename _Build_index_tuple<sizeof...(_Args)>::__type
1066 return __do_cons<_Tp>(std::move(__tuple), _Indexes());
1069 template<class _T1, class _T2>
1070 template<typename _Tp, typename... _Args, std::size_t... _Indexes>
1072 pair<_T1, _T2>::__do_cons(tuple<_Args...>&& __tuple,
1073 const _Index_tuple<_Indexes...>&)
1074 { return _Tp(std::forward<_Args>(get<_Indexes>(__tuple))...); }
1076 _GLIBCXX_END_NAMESPACE_VERSION
1079 #endif // __GXX_EXPERIMENTAL_CXX0X__
1081 #endif // _GLIBCXX_TUPLE