tuple revision 232924
1// -*- C++ -*-
2//===--------------------------- tuple ------------------------------------===//
3//
4//                     The LLVM Compiler Infrastructure
5//
6// This file is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_TUPLE
12#define _LIBCPP_TUPLE
13
14/*
15    tuple synopsis
16
17namespace std
18{
19
20template <class... T>
21class tuple {
22public:
23    constexpr tuple();
24    explicit tuple(const T&...);
25    template <class... U>
26        explicit tuple(U&&...);
27    tuple(const tuple&) = default;
28    tuple(tuple&&) = default;
29    template <class... U>
30        tuple(const tuple<U...>&);
31    template <class... U>
32        tuple(tuple<U...>&&);
33    template <class U1, class U2>
34        tuple(const pair<U1, U2>&); // iff sizeof...(T) == 2
35    template <class U1, class U2>
36        tuple(pair<U1, U2>&&); // iff sizeof...(T) == 2
37
38    // allocator-extended constructors
39    template <class Alloc>
40        tuple(allocator_arg_t, const Alloc& a);
41    template <class Alloc>
42        tuple(allocator_arg_t, const Alloc& a, const T&...);
43    template <class Alloc, class... U>
44        tuple(allocator_arg_t, const Alloc& a, U&&...);
45    template <class Alloc>
46        tuple(allocator_arg_t, const Alloc& a, const tuple&);
47    template <class Alloc>
48        tuple(allocator_arg_t, const Alloc& a, tuple&&);
49    template <class Alloc, class... U>
50        tuple(allocator_arg_t, const Alloc& a, const tuple<U...>&);
51    template <class Alloc, class... U>
52        tuple(allocator_arg_t, const Alloc& a, tuple<U...>&&);
53    template <class Alloc, class U1, class U2>
54        tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
55    template <class Alloc, class U1, class U2>
56        tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
57
58    tuple& operator=(const tuple&);
59    tuple&
60        operator=(tuple&&) noexcept(AND(is_nothrow_move_assignable<T>::value ...));
61    template <class... U>
62        tuple& operator=(const tuple<U...>&);
63    template <class... U>
64        tuple& operator=(tuple<U...>&&);
65    template <class U1, class U2>
66        tuple& operator=(const pair<U1, U2>&); // iff sizeof...(T) == 2
67    template <class U1, class U2>
68        tuple& operator=(pair<U1, U2>&&); //iffsizeof...(T) == 2
69
70    void swap(tuple&) noexcept(AND(swap(declval<T&>(), declval<T&>())...));
71};
72
73const unspecified ignore;
74
75template <class... T> tuple<V...>  make_tuple(T&&...);
76template <class... T> tuple<ATypes...> forward_as_tuple(T&&...) noexcept;
77template <class... T> tuple<T&...> tie(T&...) noexcept;
78template <class... Tuples> tuple<CTypes...> tuple_cat(Tuples&&... tpls);
79  
80// 20.4.1.4, tuple helper classes:
81template <class T> class tuple_size; // undefined
82template <class... T> class tuple_size<tuple<T...>>;
83template <intsize_t I, class T> class tuple_element; // undefined
84template <intsize_t I, class... T> class tuple_element<I, tuple<T...>>;
85
86// 20.4.1.5, element access:
87template <intsize_t I, class... T>
88    typename tuple_element<I, tuple<T...>>::type&
89    get(tuple<T...>&) noexcept;
90template <intsize_t I, class... T>
91    typename tuple_element<I, tuple<T...>>::type const&
92    get(const tuple<T...>&) noexcept;
93template <intsize_t I, class... T>
94    typename tuple_element<I, tuple<T...>>::type&&
95    get(tuple<T...>&&) noexcept;
96
97// 20.4.1.6, relational operators:
98template<class... T, class... U> bool operator==(const tuple<T...>&, const tuple<U...>&);
99template<class... T, class... U> bool operator<(const tuple<T...>&, const tuple<U...>&);
100template<class... T, class... U> bool operator!=(const tuple<T...>&, const tuple<U...>&);
101template<class... T, class... U> bool operator>(const tuple<T...>&, const tuple<U...>&);
102template<class... T, class... U> bool operator<=(const tuple<T...>&, const tuple<U...>&);
103template<class... T, class... U> bool operator>=(const tuple<T...>&, const tuple<U...>&);
104
105template <class... Types, class Alloc>
106  struct uses_allocator<tuple<Types...>, Alloc>;
107
108template <class... Types>
109  void
110  swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(noexcept(x.swap(y)));
111
112}  // std
113
114*/
115
116#include <__config>
117#include <__tuple>
118#include <cstddef>
119#include <type_traits>
120#include <__functional_base>
121#include <utility>
122
123#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
124#pragma GCC system_header
125#endif
126
127_LIBCPP_BEGIN_NAMESPACE_STD
128
129// allocator_arg_t
130
131struct _LIBCPP_VISIBLE allocator_arg_t { };
132
133extern const allocator_arg_t allocator_arg;
134
135// uses_allocator
136
137template <class _Tp>
138struct __has_allocator_type
139{
140private:
141    struct __two {char _; char __;};
142    template <class _Up> static __two __test(...);
143    template <class _Up> static char __test(typename _Up::allocator_type* = 0);
144public:
145    static const bool value = sizeof(__test<_Tp>(0)) == 1;
146};
147
148template <class _Tp, class _Alloc, bool = __has_allocator_type<_Tp>::value>
149struct __uses_allocator
150    : public integral_constant<bool,
151        is_convertible<_Alloc, typename _Tp::allocator_type>::value>
152{
153};
154
155template <class _Tp, class _Alloc>
156struct __uses_allocator<_Tp, _Alloc, false>
157    : public false_type
158{
159};
160
161template <class _Tp, class _Alloc>
162struct _LIBCPP_VISIBLE uses_allocator
163    : public __uses_allocator<_Tp, _Alloc>
164{
165};
166
167#ifndef _LIBCPP_HAS_NO_VARIADICS
168
169// uses-allocator construction
170
171template <class _Tp, class _Alloc, class ..._Args>
172struct __uses_alloc_ctor_imp
173{
174    static const bool __ua = uses_allocator<_Tp, _Alloc>::value;
175    static const bool __ic =
176        is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value;
177    static const int value = __ua ? 2 - __ic : 0;
178};
179
180template <class _Tp, class _Alloc, class ..._Args>
181struct __uses_alloc_ctor
182    : integral_constant<int, __uses_alloc_ctor_imp<_Tp, _Alloc, _Args...>::value>
183    {};
184
185#endif  // _LIBCPP_HAS_NO_VARIADICS
186
187#ifndef _LIBCPP_HAS_NO_VARIADICS
188
189// tuple_size
190
191template <class ..._Tp>
192class _LIBCPP_VISIBLE tuple_size<tuple<_Tp...> >
193    : public integral_constant<size_t, sizeof...(_Tp)>
194{
195};
196
197// tuple_element
198
199template <size_t _Ip, class ..._Tp>
200class _LIBCPP_VISIBLE tuple_element<_Ip, tuple<_Tp...> >
201{
202public:
203    typedef typename tuple_element<_Ip, __tuple_types<_Tp...> >::type type;
204};
205
206// __tuple_leaf
207
208template <size_t _Ip, class _Hp, bool=is_empty<_Hp>::value
209#if __has_feature(is_final)
210                                 && !__is_final(_Hp)
211#endif
212         >
213class __tuple_leaf;
214
215template <size_t _Ip, class _Hp, bool _Ep>
216inline _LIBCPP_INLINE_VISIBILITY
217void swap(__tuple_leaf<_Ip, _Hp, _Ep>& __x, __tuple_leaf<_Ip, _Hp, _Ep>& __y)
218    _NOEXCEPT_(__is_nothrow_swappable<_Hp>::value)
219{
220    swap(__x.get(), __y.get());
221}
222
223template <size_t _Ip, class _Hp, bool>
224class __tuple_leaf
225{
226    _Hp value;
227
228    __tuple_leaf& operator=(const __tuple_leaf&);
229public:
230    _LIBCPP_INLINE_VISIBILITY __tuple_leaf() : value()
231       {static_assert(!is_reference<_Hp>::value,
232              "Attempted to default construct a reference element in a tuple");}
233
234    template <class _Alloc>
235        _LIBCPP_INLINE_VISIBILITY
236        __tuple_leaf(integral_constant<int, 0>, const _Alloc&)
237            : value()
238        {static_assert(!is_reference<_Hp>::value,
239              "Attempted to default construct a reference element in a tuple");}
240
241    template <class _Alloc>
242        _LIBCPP_INLINE_VISIBILITY
243        __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
244            : value(allocator_arg_t(), __a)
245        {static_assert(!is_reference<_Hp>::value,
246              "Attempted to default construct a reference element in a tuple");}
247
248    template <class _Alloc>
249        _LIBCPP_INLINE_VISIBILITY
250        __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a)
251            : value(__a)
252        {static_assert(!is_reference<_Hp>::value,
253              "Attempted to default construct a reference element in a tuple");}
254
255    template <class _Tp,
256              class = typename enable_if<is_constructible<_Hp, _Tp>::value>::type>
257        _LIBCPP_INLINE_VISIBILITY
258        explicit __tuple_leaf(_Tp&& __t)
259            : value(_VSTD::forward<_Tp>(__t))
260        {static_assert(!is_reference<_Hp>::value ||
261                       (is_lvalue_reference<_Hp>::value &&
262                        (is_lvalue_reference<_Tp>::value ||
263                         is_same<typename remove_reference<_Tp>::type,
264                                 reference_wrapper<
265                                    typename remove_reference<_Hp>::type
266                                 >
267                                >::value)) ||
268                        (is_rvalue_reference<_Hp>::value &&
269                         !is_lvalue_reference<_Tp>::value),
270       "Attempted to construct a reference element in a tuple with an rvalue");}
271
272    template <class _Tp, class _Alloc>
273        _LIBCPP_INLINE_VISIBILITY
274        explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
275            : value(_VSTD::forward<_Tp>(__t))
276        {static_assert(!is_lvalue_reference<_Hp>::value ||
277                       (is_lvalue_reference<_Hp>::value &&
278                        (is_lvalue_reference<_Tp>::value ||
279                         is_same<typename remove_reference<_Tp>::type,
280                                 reference_wrapper<
281                                    typename remove_reference<_Hp>::type
282                                 >
283                                >::value)),
284       "Attempted to construct a reference element in a tuple with an rvalue");}
285
286    template <class _Tp, class _Alloc>
287        _LIBCPP_INLINE_VISIBILITY
288        explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
289            : value(allocator_arg_t(), __a, _VSTD::forward<_Tp>(__t))
290        {static_assert(!is_lvalue_reference<_Hp>::value ||
291                       (is_lvalue_reference<_Hp>::value &&
292                        (is_lvalue_reference<_Tp>::value ||
293                         is_same<typename remove_reference<_Tp>::type,
294                                 reference_wrapper<
295                                    typename remove_reference<_Hp>::type
296                                 >
297                                >::value)),
298       "Attempted to construct a reference element in a tuple with an rvalue");}
299
300    template <class _Tp, class _Alloc>
301        _LIBCPP_INLINE_VISIBILITY
302        explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
303            : value(_VSTD::forward<_Tp>(__t), __a)
304        {static_assert(!is_lvalue_reference<_Hp>::value ||
305                       (is_lvalue_reference<_Hp>::value &&
306                        (is_lvalue_reference<_Tp>::value ||
307                         is_same<typename remove_reference<_Tp>::type,
308                                 reference_wrapper<
309                                    typename remove_reference<_Hp>::type
310                                 >
311                                >::value)),
312       "Attempted to construct a reference element in a tuple with an rvalue");}
313
314    __tuple_leaf(const __tuple_leaf& __t)
315        : value(__t.get())
316        {static_assert(!is_rvalue_reference<_Hp>::value, "Can not copy a tuple with rvalue reference member");}
317
318    template <class _Tp>
319        _LIBCPP_INLINE_VISIBILITY
320        explicit __tuple_leaf(const __tuple_leaf<_Ip, _Tp>& __t)
321            : value(__t.get()) {}
322
323    template <class _Tp>
324        _LIBCPP_INLINE_VISIBILITY
325        __tuple_leaf&
326        operator=(_Tp&& __t)
327        {
328            value = _VSTD::forward<_Tp>(__t);
329            return *this;
330        }
331
332    _LIBCPP_INLINE_VISIBILITY
333    int swap(__tuple_leaf& __t) _NOEXCEPT_(__is_nothrow_swappable<__tuple_leaf>::value)
334    {
335        _VSTD::swap(*this, __t);
336        return 0;
337    }
338
339    _LIBCPP_INLINE_VISIBILITY       _Hp& get()       {return value;}
340    _LIBCPP_INLINE_VISIBILITY const _Hp& get() const {return value;}
341};
342
343template <size_t _Ip, class _Hp>
344class __tuple_leaf<_Ip, _Hp, true>
345    : private _Hp
346{
347
348    __tuple_leaf& operator=(const __tuple_leaf&);
349public:
350    _LIBCPP_INLINE_VISIBILITY __tuple_leaf() {}
351
352    template <class _Alloc>
353        _LIBCPP_INLINE_VISIBILITY
354        __tuple_leaf(integral_constant<int, 0>, const _Alloc&) {}
355
356    template <class _Alloc>
357        _LIBCPP_INLINE_VISIBILITY
358        __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
359            : _Hp(allocator_arg_t(), __a) {}
360
361    template <class _Alloc>
362        _LIBCPP_INLINE_VISIBILITY
363        __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a)
364            : _Hp(__a) {}
365
366    template <class _Tp,
367              class = typename enable_if<is_constructible<_Hp, _Tp>::value>::type>
368        _LIBCPP_INLINE_VISIBILITY
369        explicit __tuple_leaf(_Tp&& __t)
370            : _Hp(_VSTD::forward<_Tp>(__t)) {}
371
372    template <class _Tp, class _Alloc>
373        _LIBCPP_INLINE_VISIBILITY
374        explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
375            : _Hp(_VSTD::forward<_Tp>(__t)) {}
376
377    template <class _Tp, class _Alloc>
378        _LIBCPP_INLINE_VISIBILITY
379        explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
380            : _Hp(allocator_arg_t(), __a, _VSTD::forward<_Tp>(__t)) {}
381
382    template <class _Tp, class _Alloc>
383        _LIBCPP_INLINE_VISIBILITY
384        explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
385            : _Hp(_VSTD::forward<_Tp>(__t), __a) {}
386
387    template <class _Tp>
388        _LIBCPP_INLINE_VISIBILITY
389        explicit __tuple_leaf(const __tuple_leaf<_Ip, _Tp>& __t)
390            : _Hp(__t.get()) {}
391
392    template <class _Tp>
393        _LIBCPP_INLINE_VISIBILITY
394        __tuple_leaf&
395        operator=(_Tp&& __t)
396        {
397            _Hp::operator=(_VSTD::forward<_Tp>(__t));
398            return *this;
399        }
400
401    _LIBCPP_INLINE_VISIBILITY
402    int
403    swap(__tuple_leaf& __t) _NOEXCEPT_(__is_nothrow_swappable<__tuple_leaf>::value)
404    {
405        _VSTD::swap(*this, __t);
406        return 0;
407    }
408
409    _LIBCPP_INLINE_VISIBILITY       _Hp& get()       {return static_cast<_Hp&>(*this);}
410    _LIBCPP_INLINE_VISIBILITY const _Hp& get() const {return static_cast<const _Hp&>(*this);}
411};
412
413template <class ..._Tp>
414_LIBCPP_INLINE_VISIBILITY
415void __swallow(_Tp&&...) {}
416
417template <bool ...> struct __all;
418
419template <>
420struct __all<>
421{
422    static const bool value = true;
423};
424
425template <bool _B0, bool ... _Bp>
426struct __all<_B0, _Bp...>
427{
428    static const bool value = _B0 && __all<_Bp...>::value;
429};
430
431// __tuple_impl
432
433template<class _Indx, class ..._Tp> struct __tuple_impl;
434
435template<size_t ..._Indx, class ..._Tp>
436struct __tuple_impl<__tuple_indices<_Indx...>, _Tp...>
437    : public __tuple_leaf<_Indx, _Tp>...
438{
439    template <size_t ..._Uf, class ..._Tf,
440              size_t ..._Ul, class ..._Tl, class ..._Up>
441        _LIBCPP_INLINE_VISIBILITY
442        explicit
443        __tuple_impl(__tuple_indices<_Uf...>, __tuple_types<_Tf...>,
444                     __tuple_indices<_Ul...>, __tuple_types<_Tl...>,
445                     _Up&&... __u) :
446            __tuple_leaf<_Uf, _Tf>(_VSTD::forward<_Up>(__u))...,
447            __tuple_leaf<_Ul, _Tl>()...
448            {}
449
450    template <class _Alloc, size_t ..._Uf, class ..._Tf,
451              size_t ..._Ul, class ..._Tl, class ..._Up>
452        _LIBCPP_INLINE_VISIBILITY
453        explicit
454        __tuple_impl(allocator_arg_t, const _Alloc& __a,
455                     __tuple_indices<_Uf...>, __tuple_types<_Tf...>,
456                     __tuple_indices<_Ul...>, __tuple_types<_Tl...>,
457                     _Up&&... __u) :
458            __tuple_leaf<_Uf, _Tf>(__uses_alloc_ctor<_Tf, _Alloc, _Up>(), __a,
459            _VSTD::forward<_Up>(__u))...,
460            __tuple_leaf<_Ul, _Tl>(__uses_alloc_ctor<_Tl, _Alloc>(), __a)...
461            {}
462
463    template <class _Tuple,
464              class = typename enable_if
465                      <
466                         __tuple_convertible<_Tuple, tuple<_Tp...> >::value
467                      >::type
468             >
469        _LIBCPP_INLINE_VISIBILITY
470        __tuple_impl(_Tuple&& __t)
471            : __tuple_leaf<_Indx, _Tp>(_VSTD::forward<typename tuple_element<_Indx,
472                                       typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<_Indx>(__t)))...
473            {}
474
475    template <class _Alloc, class _Tuple,
476              class = typename enable_if
477                      <
478                         __tuple_convertible<_Tuple, tuple<_Tp...> >::value
479                      >::type
480             >
481        _LIBCPP_INLINE_VISIBILITY
482        __tuple_impl(allocator_arg_t, const _Alloc& __a, _Tuple&& __t)
483            : __tuple_leaf<_Indx, _Tp>(__uses_alloc_ctor<_Tp, _Alloc, typename tuple_element<_Indx,
484                                       typename __make_tuple_types<_Tuple>::type>::type>(), __a,
485                                       _VSTD::forward<typename tuple_element<_Indx,
486                                       typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<_Indx>(__t)))...
487            {}
488
489    template <class _Tuple>
490        _LIBCPP_INLINE_VISIBILITY
491        typename enable_if
492        <
493            __tuple_assignable<_Tuple, tuple<_Tp...> >::value,
494            __tuple_impl&
495        >::type
496        operator=(_Tuple&& __t)
497        {
498            __swallow(__tuple_leaf<_Indx, _Tp>::operator=(_VSTD::forward<typename tuple_element<_Indx,
499                                       typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<_Indx>(__t)))...);
500            return *this;
501        }
502
503        _LIBCPP_INLINE_VISIBILITY
504        __tuple_impl&
505        operator=(const __tuple_impl& __t)
506        {
507            __swallow(__tuple_leaf<_Indx, _Tp>::operator=(static_cast<const __tuple_leaf<_Indx, _Tp>&>(__t).get())...);
508            return *this;
509        }
510
511    _LIBCPP_INLINE_VISIBILITY
512    void swap(__tuple_impl& __t)
513        _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
514    {
515        __swallow(__tuple_leaf<_Indx, _Tp>::swap(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t))...);
516    }
517};
518
519template <class ..._Tp>
520class _LIBCPP_VISIBLE tuple
521{
522    typedef __tuple_impl<typename __make_tuple_indices<sizeof...(_Tp)>::type, _Tp...> base;
523
524    base base_;
525
526    template <size_t _Jp, class ..._Up> friend
527        typename tuple_element<_Jp, tuple<_Up...> >::type& get(tuple<_Up...>&) _NOEXCEPT;
528    template <size_t _Jp, class ..._Up> friend
529        const typename tuple_element<_Jp, tuple<_Up...> >::type& get(const tuple<_Up...>&) _NOEXCEPT;
530    template <size_t _Jp, class ..._Up> friend
531        typename tuple_element<_Jp, tuple<_Up...> >::type&& get(tuple<_Up...>&&) _NOEXCEPT;
532public:
533
534    _LIBCPP_INLINE_VISIBILITY
535    explicit tuple(const _Tp& ... __t)
536        : base_(typename __make_tuple_indices<sizeof...(_Tp)>::type(),
537                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
538                typename __make_tuple_indices<0>::type(),
539                typename __make_tuple_types<tuple, 0>::type(),
540                __t...
541               ) {}
542
543    template <class _Alloc>
544      _LIBCPP_INLINE_VISIBILITY
545      tuple(allocator_arg_t, const _Alloc& __a, const _Tp& ... __t)
546        : base_(allocator_arg_t(), __a,
547                typename __make_tuple_indices<sizeof...(_Tp)>::type(),
548                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
549                typename __make_tuple_indices<0>::type(),
550                typename __make_tuple_types<tuple, 0>::type(),
551                __t...
552               ) {}
553
554    template <class ..._Up,
555              class = typename enable_if
556                      <
557                         sizeof...(_Up) <= sizeof...(_Tp) &&
558                         __tuple_convertible
559                         <
560                            tuple<_Up...>,
561                            typename __make_tuple_types<tuple,
562                                     sizeof...(_Up) < sizeof...(_Tp) ?
563                                        sizeof...(_Up) :
564                                        sizeof...(_Tp)>::type
565                         >::value
566                      >::type
567             >
568        _LIBCPP_INLINE_VISIBILITY
569        explicit
570        tuple(_Up&&... __u)
571            : base_(typename __make_tuple_indices<sizeof...(_Up)>::type(),
572                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
573                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
574                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
575                    _VSTD::forward<_Up>(__u)...) {}
576
577    template <class _Alloc, class ..._Up,
578              class = typename enable_if
579                      <
580                         sizeof...(_Up) <= sizeof...(_Tp) &&
581                         __tuple_convertible
582                         <
583                            tuple<_Up...>,
584                            typename __make_tuple_types<tuple,
585                                     sizeof...(_Up) < sizeof...(_Tp) ?
586                                        sizeof...(_Up) :
587                                        sizeof...(_Tp)>::type
588                         >::value
589                      >::type
590             >
591        _LIBCPP_INLINE_VISIBILITY
592        tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u)
593            : base_(allocator_arg_t(), __a,
594                    typename __make_tuple_indices<sizeof...(_Up)>::type(),
595                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
596                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
597                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
598                    _VSTD::forward<_Up>(__u)...) {}
599
600    template <class _Tuple,
601              class = typename enable_if
602                      <
603                         __tuple_convertible<_Tuple, tuple>::value
604                      >::type
605             >
606        _LIBCPP_INLINE_VISIBILITY
607        tuple(_Tuple&& __t)
608            : base_(_VSTD::forward<_Tuple>(__t)) {}
609
610    template <class _Alloc, class _Tuple,
611              class = typename enable_if
612                      <
613                         __tuple_convertible<_Tuple, tuple>::value
614                      >::type
615             >
616        _LIBCPP_INLINE_VISIBILITY
617        tuple(allocator_arg_t, const _Alloc& __a, _Tuple&& __t)
618            : base_(allocator_arg_t(), __a, _VSTD::forward<_Tuple>(__t)) {}
619
620    template <class _Tuple,
621              class = typename enable_if
622                      <
623                         __tuple_assignable<_Tuple, tuple>::value
624                      >::type
625             >
626        _LIBCPP_INLINE_VISIBILITY
627        tuple&
628        operator=(_Tuple&& __t)
629        {
630            base_.operator=(_VSTD::forward<_Tuple>(__t));
631            return *this;
632        }
633
634    _LIBCPP_INLINE_VISIBILITY
635    void swap(tuple& __t) _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
636        {base_.swap(__t.base_);}
637};
638
639template <>
640class _LIBCPP_VISIBLE tuple<>
641{
642public:
643    _LIBCPP_INLINE_VISIBILITY
644    tuple() {}
645    template <class _Alloc>
646    _LIBCPP_INLINE_VISIBILITY
647        tuple(allocator_arg_t, const _Alloc&) {}
648    template <class _Alloc>
649    _LIBCPP_INLINE_VISIBILITY
650        tuple(allocator_arg_t, const _Alloc&, const tuple&) {}
651    template <class _Up>
652    _LIBCPP_INLINE_VISIBILITY
653        tuple(array<_Up, 0>) {}
654    template <class _Alloc, class _Up>
655    _LIBCPP_INLINE_VISIBILITY
656        tuple(allocator_arg_t, const _Alloc&, array<_Up, 0>) {}
657    _LIBCPP_INLINE_VISIBILITY
658    void swap(tuple&) _NOEXCEPT {}
659};
660
661template <class ..._Tp>
662inline _LIBCPP_INLINE_VISIBILITY
663typename enable_if
664<
665    __all<__is_swappable<_Tp>::value...>::value,
666    void
667>::type
668swap(tuple<_Tp...>& __t, tuple<_Tp...>& __u)
669                 _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
670    {__t.swap(__u);}
671
672// get
673
674template <size_t _Ip, class ..._Tp>
675inline _LIBCPP_INLINE_VISIBILITY
676typename tuple_element<_Ip, tuple<_Tp...> >::type&
677get(tuple<_Tp...>& __t) _NOEXCEPT
678{
679    typedef typename tuple_element<_Ip, tuple<_Tp...> >::type type;
680    return static_cast<__tuple_leaf<_Ip, type>&>(__t.base_).get();
681}
682
683template <size_t _Ip, class ..._Tp>
684inline _LIBCPP_INLINE_VISIBILITY
685const typename tuple_element<_Ip, tuple<_Tp...> >::type&
686get(const tuple<_Tp...>& __t) _NOEXCEPT
687{
688    typedef typename tuple_element<_Ip, tuple<_Tp...> >::type type;
689    return static_cast<const __tuple_leaf<_Ip, type>&>(__t.base_).get();
690}
691
692template <size_t _Ip, class ..._Tp>
693inline _LIBCPP_INLINE_VISIBILITY
694typename tuple_element<_Ip, tuple<_Tp...> >::type&&
695get(tuple<_Tp...>&& __t) _NOEXCEPT
696{
697    typedef typename tuple_element<_Ip, tuple<_Tp...> >::type type;
698    return static_cast<type&&>(
699             static_cast<__tuple_leaf<_Ip, type>&&>(__t.base_).get());
700}
701
702// tie
703
704template <class ..._Tp>
705inline _LIBCPP_INLINE_VISIBILITY
706tuple<_Tp&...>
707tie(_Tp&... __t)
708{
709    return tuple<_Tp&...>(__t...);
710}
711
712template <class _Up>
713struct __ignore_t
714{
715    template <class _Tp>
716        _LIBCPP_INLINE_VISIBILITY
717        const __ignore_t& operator=(_Tp&&) const {return *this;}
718};
719
720namespace { const __ignore_t<unsigned char> ignore = __ignore_t<unsigned char>(); }
721
722template <class _Tp> class reference_wrapper;
723
724template <class _Tp>
725struct ___make_tuple_return
726{
727    typedef _Tp type;
728};
729
730template <class _Tp>
731struct ___make_tuple_return<reference_wrapper<_Tp> >
732{
733    typedef _Tp& type;
734};
735
736template <class _Tp>
737struct __make_tuple_return
738{
739    typedef typename ___make_tuple_return<typename decay<_Tp>::type>::type type;
740};
741
742template <class... _Tp>
743inline _LIBCPP_INLINE_VISIBILITY
744tuple<typename __make_tuple_return<_Tp>::type...>
745make_tuple(_Tp&&... __t)
746{
747    return tuple<typename __make_tuple_return<_Tp>::type...>(_VSTD::forward<_Tp>(__t)...);
748}
749
750template <class... _Tp>
751inline _LIBCPP_INLINE_VISIBILITY
752tuple<_Tp&&...>
753forward_as_tuple(_Tp&&... __t)
754{
755    return tuple<_Tp&&...>(_VSTD::forward<_Tp>(__t)...);
756}
757
758template <size_t _Ip>
759struct __tuple_equal
760{
761    template <class _Tp, class _Up>
762    _LIBCPP_INLINE_VISIBILITY
763    bool operator()(const _Tp& __x, const _Up& __y)
764    {
765        return __tuple_equal<_Ip - 1>()(__x, __y) && get<_Ip-1>(__x) == get<_Ip-1>(__y);
766    }
767};
768
769template <>
770struct __tuple_equal<0>
771{
772    template <class _Tp, class _Up>
773    _LIBCPP_INLINE_VISIBILITY
774    bool operator()(const _Tp&, const _Up&)
775    {
776        return true;
777    }
778};
779
780template <class ..._Tp, class ..._Up>
781inline _LIBCPP_INLINE_VISIBILITY
782bool
783operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
784{
785    return __tuple_equal<sizeof...(_Tp)>()(__x, __y);
786}
787
788template <class ..._Tp, class ..._Up>
789inline _LIBCPP_INLINE_VISIBILITY
790bool
791operator!=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
792{
793    return !(__x == __y);
794}
795
796template <size_t _Ip>
797struct __tuple_less
798{
799    template <class _Tp, class _Up>
800    _LIBCPP_INLINE_VISIBILITY
801    bool operator()(const _Tp& __x, const _Up& __y)
802    {
803        return __tuple_less<_Ip-1>()(__x, __y) ||
804             (!__tuple_less<_Ip-1>()(__y, __x) && get<_Ip-1>(__x) < get<_Ip-1>(__y));
805    }
806};
807
808template <>
809struct __tuple_less<0>
810{
811    template <class _Tp, class _Up>
812    _LIBCPP_INLINE_VISIBILITY
813    bool operator()(const _Tp&, const _Up&)
814    {
815        return false;
816    }
817};
818
819template <class ..._Tp, class ..._Up>
820inline _LIBCPP_INLINE_VISIBILITY
821bool
822operator<(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
823{
824    return __tuple_less<sizeof...(_Tp)>()(__x, __y);
825}
826
827template <class ..._Tp, class ..._Up>
828inline _LIBCPP_INLINE_VISIBILITY
829bool
830operator>(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
831{
832    return __y < __x;
833}
834
835template <class ..._Tp, class ..._Up>
836inline _LIBCPP_INLINE_VISIBILITY
837bool
838operator>=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
839{
840    return !(__x < __y);
841}
842
843template <class ..._Tp, class ..._Up>
844inline _LIBCPP_INLINE_VISIBILITY
845bool
846operator<=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
847{
848    return !(__y < __x);
849}
850
851// tuple_cat
852
853template <class _Tp, class _Up> struct __tuple_cat_type;
854
855template <class ..._Ttypes, class ..._Utypes>
856struct __tuple_cat_type<tuple<_Ttypes...>, __tuple_types<_Utypes...> >
857{
858    typedef tuple<_Ttypes..., _Utypes...> type;
859};
860
861template <class _ResultTuple, bool _Is_Tuple0TupleLike, class ..._Tuples>
862struct __tuple_cat_return_1
863{
864};
865
866template <class ..._Types, class _Tuple0>
867struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0>
868{
869    typedef typename __tuple_cat_type<tuple<_Types...>,
870            typename __make_tuple_types<typename remove_reference<_Tuple0>::type>::type>::type
871                                                                           type;
872};
873
874template <class ..._Types, class _Tuple0, class _Tuple1, class ..._Tuples>
875struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0, _Tuple1, _Tuples...>
876    : public __tuple_cat_return_1<
877                 typename __tuple_cat_type<
878                     tuple<_Types...>,
879                     typename __make_tuple_types<typename remove_reference<_Tuple0>::type>::type
880                 >::type,
881                 __tuple_like<typename remove_reference<_Tuple1>::type>::value,
882                 _Tuple1, _Tuples...>
883{
884};
885
886template <class ..._Tuples> struct __tuple_cat_return;
887
888template <class _Tuple0, class ..._Tuples>
889struct __tuple_cat_return<_Tuple0, _Tuples...>
890    : public __tuple_cat_return_1<tuple<>,
891         __tuple_like<typename remove_reference<_Tuple0>::type>::value, _Tuple0,
892                                                                     _Tuples...>
893{
894};
895
896template <>
897struct __tuple_cat_return<>
898{
899    typedef tuple<> type;
900};
901
902inline _LIBCPP_INLINE_VISIBILITY
903tuple<>
904tuple_cat()
905{
906    return tuple<>();
907}
908
909template <class _Rp, class _Indices, class _Tuple0, class ..._Tuples>
910struct __tuple_cat_return_ref_imp;
911
912template <class ..._Types, size_t ..._I0, class _Tuple0>
913struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>, _Tuple0>
914{
915    typedef typename remove_reference<_Tuple0>::type _T0;
916    typedef tuple<_Types..., typename __apply_cv<_Tuple0,
917                          typename tuple_element<_I0, _T0>::type>::type&&...> type;
918};
919
920template <class ..._Types, size_t ..._I0, class _Tuple0, class _Tuple1, class ..._Tuples>
921struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>,
922                                  _Tuple0, _Tuple1, _Tuples...>
923    : public __tuple_cat_return_ref_imp<
924         tuple<_Types..., typename __apply_cv<_Tuple0,
925               typename tuple_element<_I0,
926                  typename remove_reference<_Tuple0>::type>::type>::type&&...>,
927         typename __make_tuple_indices<tuple_size<typename
928                                 remove_reference<_Tuple1>::type>::value>::type,
929         _Tuple1, _Tuples...>
930{
931};
932
933template <class _Tuple0, class ..._Tuples>
934struct __tuple_cat_return_ref
935    : public __tuple_cat_return_ref_imp<tuple<>,
936               typename __make_tuple_indices<
937                        tuple_size<typename remove_reference<_Tuple0>::type>::value
938               >::type, _Tuple0, _Tuples...>
939{
940};
941
942template <class _Types, class _I0, class _J0>
943struct __tuple_cat;
944
945template <class ..._Types, size_t ..._I0, size_t ..._J0>
946struct __tuple_cat<tuple<_Types...>, __tuple_indices<_I0...>, __tuple_indices<_J0...> >
947{
948    template <class _Tuple0>
949    _LIBCPP_INLINE_VISIBILITY
950    typename __tuple_cat_return_ref<tuple<_Types...>&&, _Tuple0&&>::type
951    operator()(tuple<_Types...> __t, _Tuple0&& __t0)
952    {
953        return _VSTD::forward_as_tuple(_VSTD::forward<_Types>(get<_I0>(__t))...,
954                                      get<_J0>(_VSTD::forward<_Tuple0>(__t0))...);
955    }
956
957    template <class _Tuple0, class _Tuple1, class ..._Tuples>
958    _LIBCPP_INLINE_VISIBILITY
959    typename __tuple_cat_return_ref<tuple<_Types...>&&, _Tuple0&&, _Tuple1&&, _Tuples&&...>::type
960    operator()(tuple<_Types...> __t, _Tuple0&& __t0, _Tuple1&& __t1, _Tuples&& ...__tpls)
961    {
962        typedef typename remove_reference<_Tuple0>::type _T0;
963        typedef typename remove_reference<_Tuple1>::type _T1;
964        return __tuple_cat<
965           tuple<_Types..., typename __apply_cv<_Tuple0, typename tuple_element<_J0, _T0>::type>::type&&...>,
966           typename __make_tuple_indices<sizeof ...(_Types) + tuple_size<_T0>::value>::type,
967           typename __make_tuple_indices<tuple_size<_T1>::value>::type>()
968                           (_VSTD::forward_as_tuple(
969                              _VSTD::forward<_Types>(get<_I0>(__t))...,
970                              get<_J0>(_VSTD::forward<_Tuple0>(__t0))...
971                            ),
972                            _VSTD::forward<_Tuple1>(__t1),
973                            _VSTD::forward<_Tuples>(__tpls)...);
974    }
975};
976
977template <class _Tuple0, class... _Tuples>
978inline _LIBCPP_INLINE_VISIBILITY
979typename __tuple_cat_return<_Tuple0, _Tuples...>::type
980tuple_cat(_Tuple0&& __t0, _Tuples&&... __tpls)
981{
982    typedef typename remove_reference<_Tuple0>::type _T0;
983    return __tuple_cat<tuple<>, __tuple_indices<>,
984                  typename __make_tuple_indices<tuple_size<_T0>::value>::type>()
985                  (tuple<>(), _VSTD::forward<_Tuple0>(__t0),
986                                            _VSTD::forward<_Tuples>(__tpls)...);
987}
988
989template <class ..._Tp, class _Alloc>
990struct _LIBCPP_VISIBLE uses_allocator<tuple<_Tp...>, _Alloc>
991    : true_type {};
992
993template <class _T1, class _T2>
994template <class... _Args1, class... _Args2, size_t ..._I1, size_t ..._I2>
995inline _LIBCPP_INLINE_VISIBILITY
996pair<_T1, _T2>::pair(piecewise_construct_t,
997                     tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
998                     __tuple_indices<_I1...>, __tuple_indices<_I2...>)
999    :  first(_VSTD::forward<_Args1>(get<_I1>( __first_args))...),
1000      second(_VSTD::forward<_Args2>(get<_I2>(__second_args))...)
1001{
1002}
1003
1004#endif  // _LIBCPP_HAS_NO_VARIADICS
1005
1006_LIBCPP_END_NAMESPACE_STD
1007
1008#endif  // _LIBCPP_TUPLE
1009