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 _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 _Head& _M_head() noexcept { return *this; }
115 const _Head& _M_head() const noexcept { return *this; }
118 template<std::size_t _Idx, typename _Head>
119 struct _Head_base<_Idx, _Head, false>
121 constexpr _Head_base()
124 constexpr _Head_base(const _Head& __h)
125 : _M_head_impl(__h) { }
127 template<typename _UHead, typename = typename
128 enable_if<!is_convertible<_UHead,
129 __uses_alloc_base>::value>::type>
130 _Head_base(_UHead&& __h)
131 : _M_head_impl(std::forward<_UHead>(__h)) { }
133 _Head_base(__uses_alloc0)
136 template<typename _Alloc>
137 _Head_base(__uses_alloc1<_Alloc> __a)
138 : _M_head_impl(allocator_arg, *__a._M_a) { }
140 template<typename _Alloc>
141 _Head_base(__uses_alloc2<_Alloc> __a)
142 : _M_head_impl(*__a._M_a) { }
144 template<typename _UHead>
145 _Head_base(__uses_alloc0, _UHead&& __uhead)
146 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
148 template<typename _Alloc, typename _UHead>
149 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
150 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
153 template<typename _Alloc, typename _UHead>
154 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
155 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
157 _Head& _M_head() noexcept { return _M_head_impl; }
158 const _Head& _M_head() const noexcept { return _M_head_impl; }
164 * Contains the actual implementation of the @c tuple template, stored
165 * as a recursive inheritance hierarchy from the first element (most
166 * derived class) to the last (least derived class). The @c Idx
167 * parameter gives the 0-based index of the element stored at this
168 * point in the hierarchy; we use it to implement a constant-time
171 template<std::size_t _Idx, typename... _Elements>
175 * Zero-element tuple implementation. This is the basis case for the
176 * inheritance recursion.
178 template<std::size_t _Idx>
179 struct _Tuple_impl<_Idx>
181 template<std::size_t, typename...> friend class _Tuple_impl;
183 _Tuple_impl() = default;
185 template<typename _Alloc>
186 _Tuple_impl(allocator_arg_t, const _Alloc&) { }
188 template<typename _Alloc>
189 _Tuple_impl(allocator_arg_t, const _Alloc&, const _Tuple_impl&) { }
191 template<typename _Alloc>
192 _Tuple_impl(allocator_arg_t, const _Alloc&, _Tuple_impl&&) { }
195 void _M_swap(_Tuple_impl&) noexcept { /* no-op */ }
199 * Recursive tuple implementation. Here we store the @c Head element
200 * and derive from a @c Tuple_impl containing the remaining elements
201 * (which contains the @c Tail).
203 template<std::size_t _Idx, typename _Head, typename... _Tail>
204 struct _Tuple_impl<_Idx, _Head, _Tail...>
205 : public _Tuple_impl<_Idx + 1, _Tail...>,
206 private _Head_base<_Idx, _Head, std::is_empty<_Head>::value>
208 template<std::size_t, typename...> friend class _Tuple_impl;
210 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
211 typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base;
213 _Head& _M_head() noexcept { return _Base::_M_head(); }
214 const _Head& _M_head() const noexcept { return _Base::_M_head(); }
216 _Inherited& _M_tail() noexcept { return *this; }
217 const _Inherited& _M_tail() const noexcept { return *this; }
219 constexpr _Tuple_impl()
220 : _Inherited(), _Base() { }
223 constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail)
224 : _Inherited(__tail...), _Base(__head) { }
226 template<typename _UHead, typename... _UTail, typename = typename
227 std::enable_if<sizeof...(_Tail)==sizeof...(_UTail)>::type>
229 _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
230 : _Inherited(std::forward<_UTail>(__tail)...),
231 _Base(std::forward<_UHead>(__head)) { }
233 constexpr _Tuple_impl(const _Tuple_impl&) = default;
235 _Tuple_impl(_Tuple_impl&& __in)
236 noexcept(std::is_nothrow_move_constructible<_Head>::value
237 && std::is_nothrow_move_constructible<_Inherited>::value)
238 : _Inherited(std::move(__in._M_tail())),
239 _Base(std::forward<_Head>(__in._M_head())) { }
241 template<typename... _UElements>
242 _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
243 : _Inherited(__in._M_tail()), _Base(__in._M_head()) { }
245 template<typename _UHead, typename... _UTails>
246 _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
247 : _Inherited(std::move(__in._M_tail())),
248 _Base(std::forward<_UHead>(__in._M_head())) { }
250 template<typename _Alloc>
251 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
252 : _Inherited(__tag, __a),
253 _Base(__use_alloc<_Head>(__a)) { }
255 template<typename _Alloc>
256 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
257 const _Head& __head, const _Tail&... __tail)
258 : _Inherited(__tag, __a, __tail...),
259 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { }
261 template<typename _Alloc, typename _UHead, typename... _UTail,
262 typename = typename std::enable_if<sizeof...(_Tail)
263 ==sizeof...(_UTail)>::type>
264 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
265 _UHead&& __head, _UTail&&... __tail)
266 : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
267 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
268 std::forward<_UHead>(__head)) { }
270 template<typename _Alloc>
271 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
272 const _Tuple_impl& __in)
273 : _Inherited(__tag, __a, __in._M_tail()),
274 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __in._M_head()) { }
276 template<typename _Alloc>
277 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
279 noexcept(std::is_nothrow_move_constructible<_Head>::value
280 && std::is_nothrow_move_constructible<_Inherited>::value)
281 : _Inherited(__tag, __a, std::move(__in._M_tail())),
282 _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
283 std::forward<_Head>(__in._M_head())) { }
285 template<typename _Alloc, typename... _UElements>
286 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
287 const _Tuple_impl<_Idx, _UElements...>& __in)
288 : _Inherited(__tag, __a, __in._M_tail()),
289 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __in._M_head()) { }
291 template<typename _Alloc, typename _UHead, typename... _UTails>
292 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
293 _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
294 : _Inherited(__tag, __a, std::move(__in._M_tail())),
295 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
296 std::forward<_UHead>(__in._M_head())) { }
299 operator=(const _Tuple_impl& __in)
301 _M_head() = __in._M_head();
302 _M_tail() = __in._M_tail();
307 operator=(_Tuple_impl&& __in)
308 noexcept(std::is_nothrow_move_assignable<_Head>::value
309 && std::is_nothrow_move_assignable<_Inherited>::value)
311 _M_head() = std::forward<_Head>(__in._M_head());
312 _M_tail() = std::move(__in._M_tail());
316 template<typename... _UElements>
318 operator=(const _Tuple_impl<_Idx, _UElements...>& __in)
320 _M_head() = __in._M_head();
321 _M_tail() = __in._M_tail();
325 template<typename _UHead, typename... _UTails>
327 operator=(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
329 _M_head() = std::forward<_UHead>(__in._M_head());
330 _M_tail() = std::move(__in._M_tail());
336 _M_swap(_Tuple_impl& __in)
337 noexcept(noexcept(swap(std::declval<_Head&>(),
338 std::declval<_Head&>()))
339 && noexcept(__in._M_tail()._M_swap(__in._M_tail())))
342 swap(this->_M_head(), __in._M_head());
343 _Inherited::_M_swap(__in._M_tail());
348 template<typename... _Elements>
349 class tuple : public _Tuple_impl<0, _Elements...>
351 typedef _Tuple_impl<0, _Elements...> _Inherited;
358 constexpr tuple(const _Elements&... __elements)
359 : _Inherited(__elements...) { }
361 template<typename... _UElements, typename = typename
362 std::enable_if<sizeof...(_UElements)
363 == sizeof...(_Elements)>::type>
365 tuple(_UElements&&... __elements)
366 : _Inherited(std::forward<_UElements>(__elements)...) { }
368 constexpr tuple(const tuple&) = default;
369 tuple(tuple&&) = default;
371 template<typename... _UElements, typename = typename
372 std::enable_if<sizeof...(_UElements)
373 == sizeof...(_Elements)>::type>
374 tuple(const tuple<_UElements...>& __in)
375 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
378 template<typename... _UElements, typename = typename
379 std::enable_if<sizeof...(_UElements)
380 == sizeof...(_Elements)>::type>
381 tuple(tuple<_UElements...>&& __in)
382 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
384 // allocator-extended constructors
386 template<typename _Alloc>
387 tuple(allocator_arg_t __tag, const _Alloc& __a)
388 : _Inherited(__tag, __a) { }
390 template<typename _Alloc>
391 tuple(allocator_arg_t __tag, const _Alloc& __a,
392 const _Elements&... __elements)
393 : _Inherited(__tag, __a, __elements...) { }
395 template<typename _Alloc, typename... _UElements, typename = typename
396 std::enable_if<sizeof...(_UElements)
397 == sizeof...(_Elements)>::type>
398 tuple(allocator_arg_t __tag, const _Alloc& __a,
399 _UElements&&... __elements)
400 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
403 template<typename _Alloc>
404 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
405 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
407 template<typename _Alloc>
408 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
409 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
411 template<typename _Alloc, typename... _UElements, typename = typename
412 std::enable_if<sizeof...(_UElements)
413 == sizeof...(_Elements)>::type>
414 tuple(allocator_arg_t __tag, const _Alloc& __a,
415 const tuple<_UElements...>& __in)
416 : _Inherited(__tag, __a,
417 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
420 template<typename _Alloc, typename... _UElements, typename = typename
421 std::enable_if<sizeof...(_UElements)
422 == sizeof...(_Elements)>::type>
423 tuple(allocator_arg_t __tag, const _Alloc& __a,
424 tuple<_UElements...>&& __in)
425 : _Inherited(__tag, __a,
426 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
430 operator=(const tuple& __in)
432 static_cast<_Inherited&>(*this) = __in;
437 operator=(tuple&& __in)
438 noexcept(std::is_nothrow_move_assignable<_Inherited>::value)
440 static_cast<_Inherited&>(*this) = std::move(__in);
444 template<typename... _UElements, typename = typename
445 std::enable_if<sizeof...(_UElements)
446 == sizeof...(_Elements)>::type>
448 operator=(const tuple<_UElements...>& __in)
450 static_cast<_Inherited&>(*this) = __in;
454 template<typename... _UElements, typename = typename
455 std::enable_if<sizeof...(_UElements)
456 == sizeof...(_Elements)>::type>
458 operator=(tuple<_UElements...>&& __in)
460 static_cast<_Inherited&>(*this) = std::move(__in);
466 noexcept(noexcept(__in._M_swap(__in)))
467 { _Inherited::_M_swap(__in); }
474 void swap(tuple&) noexcept { /* no-op */ }
477 /// tuple (2-element), with construction and assignment from a pair.
478 template<typename _T1, typename _T2>
479 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
481 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
488 constexpr tuple(const _T1& __a1, const _T2& __a2)
489 : _Inherited(__a1, __a2) { }
491 template<typename _U1, typename _U2>
493 tuple(_U1&& __a1, _U2&& __a2)
494 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
496 constexpr tuple(const tuple&) = default;
497 tuple(tuple&&) = default;
499 template<typename _U1, typename _U2>
500 tuple(const tuple<_U1, _U2>& __in)
501 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
503 template<typename _U1, typename _U2>
504 tuple(tuple<_U1, _U2>&& __in)
505 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
507 template<typename _U1, typename _U2>
508 tuple(const pair<_U1, _U2>& __in)
509 : _Inherited(__in.first, __in.second) { }
511 template<typename _U1, typename _U2>
512 tuple(pair<_U1, _U2>&& __in)
513 : _Inherited(std::forward<_U1>(__in.first),
514 std::forward<_U2>(__in.second)) { }
516 // allocator-extended constructors
518 template<typename _Alloc>
519 tuple(allocator_arg_t __tag, const _Alloc& __a)
520 : _Inherited(__tag, __a) { }
522 template<typename _Alloc>
523 tuple(allocator_arg_t __tag, const _Alloc& __a,
524 const _T1& __a1, const _T2& __a2)
525 : _Inherited(__tag, __a, __a1, __a2) { }
527 template<typename _Alloc, typename _U1, typename _U2>
528 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
529 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
530 std::forward<_U2>(__a2)) { }
532 template<typename _Alloc>
533 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
534 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
536 template<typename _Alloc>
537 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
538 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
540 template<typename _Alloc, typename _U1, typename _U2>
541 tuple(allocator_arg_t __tag, const _Alloc& __a,
542 const tuple<_U1, _U2>& __in)
543 : _Inherited(__tag, __a,
544 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
547 template<typename _Alloc, typename _U1, typename _U2>
548 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
549 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
552 template<typename _Alloc, typename _U1, typename _U2>
553 tuple(allocator_arg_t __tag, const _Alloc& __a,
554 const pair<_U1, _U2>& __in)
555 : _Inherited(__tag, __a, __in.first, __in.second) { }
557 template<typename _Alloc, typename _U1, typename _U2>
558 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
559 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
560 std::forward<_U2>(__in.second)) { }
563 operator=(const tuple& __in)
565 static_cast<_Inherited&>(*this) = __in;
570 operator=(tuple&& __in)
571 noexcept(std::is_nothrow_move_assignable<_Inherited>::value)
573 static_cast<_Inherited&>(*this) = std::move(__in);
577 template<typename _U1, typename _U2>
579 operator=(const tuple<_U1, _U2>& __in)
581 static_cast<_Inherited&>(*this) = __in;
585 template<typename _U1, typename _U2>
587 operator=(tuple<_U1, _U2>&& __in)
589 static_cast<_Inherited&>(*this) = std::move(__in);
593 template<typename _U1, typename _U2>
595 operator=(const pair<_U1, _U2>& __in)
597 this->_M_head() = __in.first;
598 this->_M_tail()._M_head() = __in.second;
602 template<typename _U1, typename _U2>
604 operator=(pair<_U1, _U2>&& __in)
606 this->_M_head() = std::forward<_U1>(__in.first);
607 this->_M_tail()._M_head() = std::forward<_U2>(__in.second);
613 noexcept(noexcept(__in._M_swap(__in)))
614 { _Inherited::_M_swap(__in); }
617 /// tuple (1-element).
618 template<typename _T1>
619 class tuple<_T1> : public _Tuple_impl<0, _T1>
621 typedef _Tuple_impl<0, _T1> _Inherited;
628 constexpr tuple(const _T1& __a1)
629 : _Inherited(__a1) { }
631 template<typename _U1, typename = typename
632 std::enable_if<std::is_constructible<_T1, _U1&&>::value>::type>
635 : _Inherited(std::forward<_U1>(__a1)) { }
637 constexpr tuple(const tuple&) = default;
638 tuple(tuple&&) = default;
640 template<typename _U1>
641 tuple(const tuple<_U1>& __in)
642 : _Inherited(static_cast<const _Tuple_impl<0, _U1>&>(__in)) { }
644 template<typename _U1>
645 tuple(tuple<_U1>&& __in)
646 : _Inherited(static_cast<_Tuple_impl<0, _U1>&&>(__in)) { }
648 // allocator-extended constructors
650 template<typename _Alloc>
651 tuple(allocator_arg_t __tag, const _Alloc& __a)
652 : _Inherited(__tag, __a) { }
654 template<typename _Alloc>
655 tuple(allocator_arg_t __tag, const _Alloc& __a, const _T1& __a1)
656 : _Inherited(__tag, __a, __a1) { }
658 // TODO: constrain for is_uses_allocator_constructible<_T1, _U1&&, _Alloc>
659 template<typename _Alloc, typename _U1>
660 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1)
661 : _Inherited(__tag, __a, std::forward<_U1>(__a1)) { }
663 template<typename _Alloc>
664 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
665 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
667 template<typename _Alloc>
668 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
669 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
671 template<typename _Alloc, typename _U1>
672 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple<_U1>& __in)
673 : _Inherited(__tag, __a, static_cast<const _Tuple_impl<0, _U1>&>(__in))
676 template<typename _Alloc, typename _U1>
677 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1>&& __in)
678 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1>&&>(__in)) { }
681 operator=(const tuple& __in)
683 static_cast<_Inherited&>(*this) = __in;
688 operator=(tuple&& __in)
689 noexcept(std::is_nothrow_move_assignable<_Inherited>::value)
691 static_cast<_Inherited&>(*this) = std::move(__in);
695 template<typename _U1>
697 operator=(const tuple<_U1>& __in)
699 static_cast<_Inherited&>(*this) = __in;
703 template<typename _U1>
705 operator=(tuple<_U1>&& __in)
707 static_cast<_Inherited&>(*this) = std::move(__in);
713 noexcept(noexcept(__in._M_swap(__in)))
714 { _Inherited::_M_swap(__in); }
718 /// Gives the type of the ith element of a given tuple type.
719 template<std::size_t __i, typename _Tp>
720 struct tuple_element;
723 * Recursive case for tuple_element: strip off the first element in
724 * the tuple and retrieve the (i-1)th element of the remaining tuple.
726 template<std::size_t __i, typename _Head, typename... _Tail>
727 struct tuple_element<__i, tuple<_Head, _Tail...> >
728 : tuple_element<__i - 1, tuple<_Tail...> > { };
731 * Basis case for tuple_element: The first element is the one we're seeking.
733 template<typename _Head, typename... _Tail>
734 struct tuple_element<0, tuple<_Head, _Tail...> >
739 template<std::size_t __i, typename _Tp>
740 struct tuple_element<__i, const _Tp>
743 add_const<typename tuple_element<__i, _Tp>::type>::type type;
746 template<std::size_t __i, typename _Tp>
747 struct tuple_element<__i, volatile _Tp>
750 add_volatile<typename tuple_element<__i, _Tp>::type>::type type;
753 template<std::size_t __i, typename _Tp>
754 struct tuple_element<__i, const volatile _Tp>
757 add_cv<typename tuple_element<__i, _Tp>::type>::type type;
760 /// Finds the size of a given tuple type.
761 template<typename _Tp>
764 template<typename _Tp>
765 struct tuple_size<const _Tp>
766 : public integral_constant<
767 typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
768 tuple_size<_Tp>::value> { };
770 template<typename _Tp>
771 struct tuple_size<volatile _Tp>
772 : public integral_constant<
773 typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
774 tuple_size<_Tp>::value> { };
776 template<typename _Tp>
777 struct tuple_size<const volatile _Tp>
778 : public integral_constant<
779 typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
780 tuple_size<_Tp>::value> { };
783 template<typename... _Elements>
784 struct tuple_size<tuple<_Elements...>>
785 : public integral_constant<std::size_t, sizeof...(_Elements)> { };
787 template<std::size_t __i, typename _Head, typename... _Tail>
788 inline typename __add_ref<_Head>::type
789 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
790 { return __t._M_head(); }
792 template<std::size_t __i, typename _Head, typename... _Tail>
793 inline typename __add_c_ref<_Head>::type
794 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
795 { return __t._M_head(); }
797 // Return a reference (const reference, rvalue reference) to the ith element
798 // of a tuple. Any const or non-const ref elements are returned with their
800 template<std::size_t __i, typename... _Elements>
801 inline typename __add_ref<
802 typename tuple_element<__i, tuple<_Elements...>>::type
804 get(tuple<_Elements...>& __t) noexcept
805 { return __get_helper<__i>(__t); }
807 template<std::size_t __i, typename... _Elements>
808 inline typename __add_c_ref<
809 typename tuple_element<__i, tuple<_Elements...>>::type
811 get(const tuple<_Elements...>& __t) noexcept
812 { return __get_helper<__i>(__t); }
814 template<std::size_t __i, typename... _Elements>
815 inline typename __add_r_ref<
816 typename tuple_element<__i, tuple<_Elements...>>::type
818 get(tuple<_Elements...>&& __t) noexcept
819 { return std::forward<typename tuple_element<__i,
820 tuple<_Elements...>>::type&&>(get<__i>(__t)); }
822 // This class helps construct the various comparison operations on tuples
823 template<std::size_t __check_equal_size, std::size_t __i, std::size_t __j,
824 typename _Tp, typename _Up>
825 struct __tuple_compare;
827 template<std::size_t __i, std::size_t __j, typename _Tp, typename _Up>
828 struct __tuple_compare<0, __i, __j, _Tp, _Up>
830 static bool __eq(const _Tp& __t, const _Up& __u)
832 return (get<__i>(__t) == get<__i>(__u) &&
833 __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__eq(__t, __u));
836 static bool __less(const _Tp& __t, const _Up& __u)
838 return ((get<__i>(__t) < get<__i>(__u))
839 || !(get<__i>(__u) < get<__i>(__t)) &&
840 __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__less(__t, __u));
844 template<std::size_t __i, typename _Tp, typename _Up>
845 struct __tuple_compare<0, __i, __i, _Tp, _Up>
847 static bool __eq(const _Tp&, const _Up&)
850 static bool __less(const _Tp&, const _Up&)
854 template<typename... _TElements, typename... _UElements>
856 operator==(const tuple<_TElements...>& __t,
857 const tuple<_UElements...>& __u)
859 typedef tuple<_TElements...> _Tp;
860 typedef tuple<_UElements...> _Up;
861 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value,
862 0, tuple_size<_Tp>::value, _Tp, _Up>::__eq(__t, __u));
865 template<typename... _TElements, typename... _UElements>
867 operator<(const tuple<_TElements...>& __t,
868 const tuple<_UElements...>& __u)
870 typedef tuple<_TElements...> _Tp;
871 typedef tuple<_UElements...> _Up;
872 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value,
873 0, tuple_size<_Tp>::value, _Tp, _Up>::__less(__t, __u));
876 template<typename... _TElements, typename... _UElements>
878 operator!=(const tuple<_TElements...>& __t,
879 const tuple<_UElements...>& __u)
880 { return !(__t == __u); }
882 template<typename... _TElements, typename... _UElements>
884 operator>(const tuple<_TElements...>& __t,
885 const tuple<_UElements...>& __u)
886 { return __u < __t; }
888 template<typename... _TElements, typename... _UElements>
890 operator<=(const tuple<_TElements...>& __t,
891 const tuple<_UElements...>& __u)
892 { return !(__u < __t); }
894 template<typename... _TElements, typename... _UElements>
896 operator>=(const tuple<_TElements...>& __t,
897 const tuple<_UElements...>& __u)
898 { return !(__t < __u); }
901 template<typename... _Elements>
902 inline tuple<typename __decay_and_strip<_Elements>::__type...>
903 make_tuple(_Elements&&... __args)
905 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
907 return __result_type(std::forward<_Elements>(__args)...);
910 template<typename... _Elements>
911 inline tuple<_Elements&&...>
912 forward_as_tuple(_Elements&&... __args) noexcept
913 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
915 template<std::size_t...> struct __index_holder { };
917 template<std::size_t __i, typename _IdxHolder, typename... _Elements>
918 struct __index_holder_impl;
920 template<std::size_t __i, std::size_t... _Indexes, typename _IdxHolder,
921 typename... _Elements>
922 struct __index_holder_impl<__i, __index_holder<_Indexes...>,
923 _IdxHolder, _Elements...>
925 typedef typename __index_holder_impl<__i + 1,
926 __index_holder<_Indexes..., __i>,
927 _Elements...>::type type;
930 template<std::size_t __i, std::size_t... _Indexes>
931 struct __index_holder_impl<__i, __index_holder<_Indexes...> >
932 { typedef __index_holder<_Indexes...> type; };
934 template<typename... _Elements>
935 struct __make_index_holder
936 : __index_holder_impl<0, __index_holder<>, _Elements...> { };
938 template<typename... _TElements, std::size_t... _TIdx,
939 typename... _UElements, std::size_t... _UIdx>
940 inline tuple<_TElements..., _UElements...>
941 __tuple_cat_helper(const tuple<_TElements...>& __t,
942 const __index_holder<_TIdx...>&,
943 const tuple<_UElements...>& __u,
944 const __index_holder<_UIdx...>&)
945 { return tuple<_TElements..., _UElements...>(get<_TIdx>(__t)...,
946 get<_UIdx>(__u)...); }
948 template<typename... _TElements, std::size_t... _TIdx,
949 typename... _UElements, std::size_t... _UIdx>
950 inline tuple<_TElements..., _UElements...>
951 __tuple_cat_helper(tuple<_TElements...>&& __t,
952 const __index_holder<_TIdx...>&,
953 const tuple<_UElements...>& __u,
954 const __index_holder<_UIdx...>&)
955 { return tuple<_TElements..., _UElements...>
956 (std::forward<_TElements>(get<_TIdx>(__t))..., get<_UIdx>(__u)...); }
958 template<typename... _TElements, std::size_t... _TIdx,
959 typename... _UElements, std::size_t... _UIdx>
960 inline tuple<_TElements..., _UElements...>
961 __tuple_cat_helper(const tuple<_TElements...>& __t,
962 const __index_holder<_TIdx...>&,
963 tuple<_UElements...>&& __u,
964 const __index_holder<_UIdx...>&)
965 { return tuple<_TElements..., _UElements...>
966 (get<_TIdx>(__t)..., std::forward<_UElements>(get<_UIdx>(__u))...); }
968 template<typename... _TElements, std::size_t... _TIdx,
969 typename... _UElements, std::size_t... _UIdx>
970 inline tuple<_TElements..., _UElements...>
971 __tuple_cat_helper(tuple<_TElements...>&& __t,
972 const __index_holder<_TIdx...>&,
973 tuple<_UElements...>&& __u,
974 const __index_holder<_UIdx...>&)
975 { return tuple<_TElements..., _UElements...>
976 (std::forward<_TElements>(get<_TIdx>(__t))...,
977 std::forward<_UElements>(get<_UIdx>(__u))...); }
979 template<typename... _TElements, typename... _UElements>
980 inline tuple<_TElements..., _UElements...>
981 tuple_cat(const tuple<_TElements...>& __t, const tuple<_UElements...>& __u)
983 return __tuple_cat_helper(__t, typename
984 __make_index_holder<_TElements...>::type(),
986 __make_index_holder<_UElements...>::type());
989 template<typename... _TElements, typename... _UElements>
990 inline tuple<_TElements..., _UElements...>
991 tuple_cat(tuple<_TElements...>&& __t, const tuple<_UElements...>& __u)
993 return __tuple_cat_helper(std::move(__t), typename
994 __make_index_holder<_TElements...>::type(),
996 __make_index_holder<_UElements...>::type());
999 template<typename... _TElements, typename... _UElements>
1000 inline tuple<_TElements..., _UElements...>
1001 tuple_cat(const tuple<_TElements...>& __t, tuple<_UElements...>&& __u)
1003 return __tuple_cat_helper(__t, typename
1004 __make_index_holder<_TElements...>::type(),
1005 std::move(__u), typename
1006 __make_index_holder<_UElements...>::type());
1009 template<typename... _TElements, typename... _UElements>
1010 inline tuple<_TElements..., _UElements...>
1011 tuple_cat(tuple<_TElements...>&& __t, tuple<_UElements...>&& __u)
1013 return __tuple_cat_helper(std::move(__t), typename
1014 __make_index_holder<_TElements...>::type(),
1015 std::move(__u), typename
1016 __make_index_holder<_UElements...>::type());
1019 template<typename... _Elements>
1020 inline tuple<_Elements&...>
1021 tie(_Elements&... __args) noexcept
1022 { return tuple<_Elements&...>(__args...); }
1024 template<typename... _Elements>
1026 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
1027 noexcept(noexcept(__x.swap(__y)))
1030 // A class (and instance) which can be used in 'tie' when an element
1031 // of a tuple is not required
1032 struct _Swallow_assign
1035 const _Swallow_assign&
1036 operator=(const _Tp&) const
1040 const _Swallow_assign ignore{};
1042 /// Partial specialization for tuples
1043 template<typename... _Types, typename _Alloc>
1044 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
1047 * Stores a tuple of indices. Used by bind() to extract the elements
1050 template<int... _Indexes>
1053 typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next;
1056 /// Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
1057 template<std::size_t _Num>
1058 struct _Build_index_tuple
1060 typedef typename _Build_index_tuple<_Num-1>::__type::__next __type;
1064 struct _Build_index_tuple<0>
1066 typedef _Index_tuple<> __type;
1069 // See stl_pair.h...
1070 template<class _T1, class _T2>
1071 template<typename _Tp, typename... _Args>
1074 __cons(tuple<_Args...>&& __tuple)
1076 typedef typename _Build_index_tuple<sizeof...(_Args)>::__type
1078 return __do_cons<_Tp>(std::move(__tuple), _Indexes());
1081 template<class _T1, class _T2>
1082 template<typename _Tp, typename... _Args, int... _Indexes>
1085 __do_cons(tuple<_Args...>&& __tuple,
1086 const _Index_tuple<_Indexes...>&)
1087 { return _Tp(std::forward<_Args>(get<_Indexes>(__tuple))...); }
1089 _GLIBCXX_END_NAMESPACE_VERSION
1092 #endif // __GXX_EXPERIMENTAL_CXX0X__
1094 #endif // _GLIBCXX_TUPLE