xref: /llvm-project-15.0.7/libcxx/include/tuple (revision 0bf886d4)
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    void swap(__tuple_impl& __t)
505        _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
506    {
507        __swallow(__tuple_leaf<_Indx, _Tp>::swap(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t))...);
508    }
509};
510
511template <class ..._Tp>
512class _LIBCPP_VISIBLE tuple
513{
514    typedef __tuple_impl<typename __make_tuple_indices<sizeof...(_Tp)>::type, _Tp...> base;
515
516    base base_;
517
518    template <size_t _Jp, class ..._Up> friend
519        typename tuple_element<_Jp, tuple<_Up...> >::type& get(tuple<_Up...>&) _NOEXCEPT;
520    template <size_t _Jp, class ..._Up> friend
521        const typename tuple_element<_Jp, tuple<_Up...> >::type& get(const tuple<_Up...>&) _NOEXCEPT;
522    template <size_t _Jp, class ..._Up> friend
523        typename tuple_element<_Jp, tuple<_Up...> >::type&& get(tuple<_Up...>&&) _NOEXCEPT;
524public:
525
526    _LIBCPP_INLINE_VISIBILITY
527    explicit tuple(const _Tp& ... __t)
528        : base_(typename __make_tuple_indices<sizeof...(_Tp)>::type(),
529                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
530                typename __make_tuple_indices<0>::type(),
531                typename __make_tuple_types<tuple, 0>::type(),
532                __t...
533               ) {}
534
535    template <class _Alloc>
536      _LIBCPP_INLINE_VISIBILITY
537      tuple(allocator_arg_t, const _Alloc& __a, const _Tp& ... __t)
538        : base_(allocator_arg_t(), __a,
539                typename __make_tuple_indices<sizeof...(_Tp)>::type(),
540                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
541                typename __make_tuple_indices<0>::type(),
542                typename __make_tuple_types<tuple, 0>::type(),
543                __t...
544               ) {}
545
546    template <class ..._Up,
547              class = typename enable_if
548                      <
549                         sizeof...(_Up) <= sizeof...(_Tp) &&
550                         __tuple_convertible
551                         <
552                            tuple<_Up...>,
553                            typename __make_tuple_types<tuple,
554                                     sizeof...(_Up) < sizeof...(_Tp) ?
555                                        sizeof...(_Up) :
556                                        sizeof...(_Tp)>::type
557                         >::value
558                      >::type
559             >
560        _LIBCPP_INLINE_VISIBILITY
561        explicit
562        tuple(_Up&&... __u)
563            : base_(typename __make_tuple_indices<sizeof...(_Up)>::type(),
564                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
565                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
566                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
567                    _VSTD::forward<_Up>(__u)...) {}
568
569    template <class _Alloc, class ..._Up,
570              class = typename enable_if
571                      <
572                         sizeof...(_Up) <= sizeof...(_Tp) &&
573                         __tuple_convertible
574                         <
575                            tuple<_Up...>,
576                            typename __make_tuple_types<tuple,
577                                     sizeof...(_Up) < sizeof...(_Tp) ?
578                                        sizeof...(_Up) :
579                                        sizeof...(_Tp)>::type
580                         >::value
581                      >::type
582             >
583        _LIBCPP_INLINE_VISIBILITY
584        tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u)
585            : base_(allocator_arg_t(), __a,
586                    typename __make_tuple_indices<sizeof...(_Up)>::type(),
587                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
588                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
589                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
590                    _VSTD::forward<_Up>(__u)...) {}
591
592    template <class _Tuple,
593              class = typename enable_if
594                      <
595                         __tuple_convertible<_Tuple, tuple>::value
596                      >::type
597             >
598        _LIBCPP_INLINE_VISIBILITY
599        tuple(_Tuple&& __t)
600            : base_(_VSTD::forward<_Tuple>(__t)) {}
601
602    template <class _Alloc, class _Tuple,
603              class = typename enable_if
604                      <
605                         __tuple_convertible<_Tuple, tuple>::value
606                      >::type
607             >
608        _LIBCPP_INLINE_VISIBILITY
609        tuple(allocator_arg_t, const _Alloc& __a, _Tuple&& __t)
610            : base_(allocator_arg_t(), __a, _VSTD::forward<_Tuple>(__t)) {}
611
612    template <class _Tuple,
613              class = typename enable_if
614                      <
615                         __tuple_assignable<_Tuple, tuple>::value
616                      >::type
617             >
618        _LIBCPP_INLINE_VISIBILITY
619        tuple&
620        operator=(_Tuple&& __t)
621        {
622            base_.operator=(_VSTD::forward<_Tuple>(__t));
623            return *this;
624        }
625
626    _LIBCPP_INLINE_VISIBILITY
627    void swap(tuple& __t) _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
628        {base_.swap(__t.base_);}
629};
630
631template <>
632class _LIBCPP_VISIBLE tuple<>
633{
634public:
635    _LIBCPP_INLINE_VISIBILITY
636    tuple() {}
637    template <class _Alloc>
638    _LIBCPP_INLINE_VISIBILITY
639        tuple(allocator_arg_t, const _Alloc&) {}
640    template <class _Alloc>
641    _LIBCPP_INLINE_VISIBILITY
642        tuple(allocator_arg_t, const _Alloc&, const tuple&) {}
643    template <class _Up>
644    _LIBCPP_INLINE_VISIBILITY
645        tuple(array<_Up, 0>) {}
646    template <class _Alloc, class _Up>
647    _LIBCPP_INLINE_VISIBILITY
648        tuple(allocator_arg_t, const _Alloc&, array<_Up, 0>) {}
649    _LIBCPP_INLINE_VISIBILITY
650    void swap(tuple&) _NOEXCEPT {}
651};
652
653template <class ..._Tp>
654inline _LIBCPP_INLINE_VISIBILITY
655typename enable_if
656<
657    __all<__is_swappable<_Tp>::value...>::value,
658    void
659>::type
660swap(tuple<_Tp...>& __t, tuple<_Tp...>& __u)
661                 _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
662    {__t.swap(__u);}
663
664// get
665
666template <size_t _Ip, class ..._Tp>
667inline _LIBCPP_INLINE_VISIBILITY
668typename tuple_element<_Ip, tuple<_Tp...> >::type&
669get(tuple<_Tp...>& __t) _NOEXCEPT
670{
671    typedef typename tuple_element<_Ip, tuple<_Tp...> >::type type;
672    return static_cast<__tuple_leaf<_Ip, type>&>(__t.base_).get();
673}
674
675template <size_t _Ip, class ..._Tp>
676inline _LIBCPP_INLINE_VISIBILITY
677const typename tuple_element<_Ip, tuple<_Tp...> >::type&
678get(const tuple<_Tp...>& __t) _NOEXCEPT
679{
680    typedef typename tuple_element<_Ip, tuple<_Tp...> >::type type;
681    return static_cast<const __tuple_leaf<_Ip, type>&>(__t.base_).get();
682}
683
684template <size_t _Ip, class ..._Tp>
685inline _LIBCPP_INLINE_VISIBILITY
686typename tuple_element<_Ip, tuple<_Tp...> >::type&&
687get(tuple<_Tp...>&& __t) _NOEXCEPT
688{
689    typedef typename tuple_element<_Ip, tuple<_Tp...> >::type type;
690    return static_cast<type&&>(
691             static_cast<__tuple_leaf<_Ip, type>&&>(__t.base_).get());
692}
693
694// tie
695
696template <class ..._Tp>
697inline _LIBCPP_INLINE_VISIBILITY
698tuple<_Tp&...>
699tie(_Tp&... __t)
700{
701    return tuple<_Tp&...>(__t...);
702}
703
704template <class _Up>
705struct __ignore_t
706{
707    template <class _Tp>
708        _LIBCPP_INLINE_VISIBILITY
709        const __ignore_t& operator=(_Tp&&) const {return *this;}
710};
711
712namespace { const __ignore_t<unsigned char> ignore = __ignore_t<unsigned char>(); }
713
714template <class _Tp> class reference_wrapper;
715
716template <class _Tp>
717struct ___make_tuple_return
718{
719    typedef _Tp type;
720};
721
722template <class _Tp>
723struct ___make_tuple_return<reference_wrapper<_Tp> >
724{
725    typedef _Tp& type;
726};
727
728template <class _Tp>
729struct __make_tuple_return
730{
731    typedef typename ___make_tuple_return<typename decay<_Tp>::type>::type type;
732};
733
734template <class... _Tp>
735inline _LIBCPP_INLINE_VISIBILITY
736tuple<typename __make_tuple_return<_Tp>::type...>
737make_tuple(_Tp&&... __t)
738{
739    return tuple<typename __make_tuple_return<_Tp>::type...>(_VSTD::forward<_Tp>(__t)...);
740}
741
742template <class... _Tp>
743inline _LIBCPP_INLINE_VISIBILITY
744tuple<_Tp&&...>
745forward_as_tuple(_Tp&&... __t)
746{
747    return tuple<_Tp&&...>(_VSTD::forward<_Tp>(__t)...);
748}
749
750template <size_t _Ip>
751struct __tuple_equal
752{
753    template <class _Tp, class _Up>
754    _LIBCPP_INLINE_VISIBILITY
755    bool operator()(const _Tp& __x, const _Up& __y)
756    {
757        return __tuple_equal<_Ip - 1>()(__x, __y) && get<_Ip-1>(__x) == get<_Ip-1>(__y);
758    }
759};
760
761template <>
762struct __tuple_equal<0>
763{
764    template <class _Tp, class _Up>
765    _LIBCPP_INLINE_VISIBILITY
766    bool operator()(const _Tp&, const _Up&)
767    {
768        return true;
769    }
770};
771
772template <class ..._Tp, class ..._Up>
773inline _LIBCPP_INLINE_VISIBILITY
774bool
775operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
776{
777    return __tuple_equal<sizeof...(_Tp)>()(__x, __y);
778}
779
780template <class ..._Tp, class ..._Up>
781inline _LIBCPP_INLINE_VISIBILITY
782bool
783operator!=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
784{
785    return !(__x == __y);
786}
787
788template <size_t _Ip>
789struct __tuple_less
790{
791    template <class _Tp, class _Up>
792    _LIBCPP_INLINE_VISIBILITY
793    bool operator()(const _Tp& __x, const _Up& __y)
794    {
795        return __tuple_less<_Ip-1>()(__x, __y) ||
796             (!__tuple_less<_Ip-1>()(__y, __x) && get<_Ip-1>(__x) < get<_Ip-1>(__y));
797    }
798};
799
800template <>
801struct __tuple_less<0>
802{
803    template <class _Tp, class _Up>
804    _LIBCPP_INLINE_VISIBILITY
805    bool operator()(const _Tp&, const _Up&)
806    {
807        return false;
808    }
809};
810
811template <class ..._Tp, class ..._Up>
812inline _LIBCPP_INLINE_VISIBILITY
813bool
814operator<(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
815{
816    return __tuple_less<sizeof...(_Tp)>()(__x, __y);
817}
818
819template <class ..._Tp, class ..._Up>
820inline _LIBCPP_INLINE_VISIBILITY
821bool
822operator>(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
823{
824    return __y < __x;
825}
826
827template <class ..._Tp, class ..._Up>
828inline _LIBCPP_INLINE_VISIBILITY
829bool
830operator>=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
831{
832    return !(__x < __y);
833}
834
835template <class ..._Tp, class ..._Up>
836inline _LIBCPP_INLINE_VISIBILITY
837bool
838operator<=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
839{
840    return !(__y < __x);
841}
842
843// tuple_cat
844
845template <class _Tp, class _Up> struct __tuple_cat_type;
846
847template <class ..._Ttypes, class ..._Utypes>
848struct __tuple_cat_type<tuple<_Ttypes...>, __tuple_types<_Utypes...> >
849{
850    typedef tuple<_Ttypes..., _Utypes...> type;
851};
852
853template <class _ResultTuple, bool _Is_Tuple0TupleLike, class ..._Tuples>
854struct __tuple_cat_return_1
855{
856};
857
858template <class ..._Types, class _Tuple0>
859struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0>
860{
861    typedef typename __tuple_cat_type<tuple<_Types...>,
862            typename __make_tuple_types<typename remove_reference<_Tuple0>::type>::type>::type
863                                                                           type;
864};
865
866template <class ..._Types, class _Tuple0, class _Tuple1, class ..._Tuples>
867struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0, _Tuple1, _Tuples...>
868    : public __tuple_cat_return_1<
869                 typename __tuple_cat_type<
870                     tuple<_Types...>,
871                     typename __make_tuple_types<typename remove_reference<_Tuple0>::type>::type
872                 >::type,
873                 __tuple_like<typename remove_reference<_Tuple1>::type>::value,
874                 _Tuple1, _Tuples...>
875{
876};
877
878template <class ..._Tuples> struct __tuple_cat_return;
879
880template <class _Tuple0, class ..._Tuples>
881struct __tuple_cat_return<_Tuple0, _Tuples...>
882    : public __tuple_cat_return_1<tuple<>,
883         __tuple_like<typename remove_reference<_Tuple0>::type>::value, _Tuple0,
884                                                                     _Tuples...>
885{
886};
887
888template <>
889struct __tuple_cat_return<>
890{
891    typedef tuple<> type;
892};
893
894inline _LIBCPP_INLINE_VISIBILITY
895tuple<>
896tuple_cat()
897{
898    return tuple<>();
899}
900
901template <class _Rp, class _Indices, class _Tuple0, class ..._Tuples>
902struct __tuple_cat_return_ref_imp;
903
904template <class ..._Types, size_t ..._I0, class _Tuple0>
905struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>, _Tuple0>
906{
907    typedef typename remove_reference<_Tuple0>::type _T0;
908    typedef tuple<_Types..., typename __apply_cv<_Tuple0,
909                          typename tuple_element<_I0, _T0>::type>::type&&...> type;
910};
911
912template <class ..._Types, size_t ..._I0, class _Tuple0, class _Tuple1, class ..._Tuples>
913struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>,
914                                  _Tuple0, _Tuple1, _Tuples...>
915    : public __tuple_cat_return_ref_imp<
916         tuple<_Types..., typename __apply_cv<_Tuple0,
917               typename tuple_element<_I0,
918                  typename remove_reference<_Tuple0>::type>::type>::type&&...>,
919         typename __make_tuple_indices<tuple_size<typename
920                                 remove_reference<_Tuple1>::type>::value>::type,
921         _Tuple1, _Tuples...>
922{
923};
924
925template <class _Tuple0, class ..._Tuples>
926struct __tuple_cat_return_ref
927    : public __tuple_cat_return_ref_imp<tuple<>,
928               typename __make_tuple_indices<
929                        tuple_size<typename remove_reference<_Tuple0>::type>::value
930               >::type, _Tuple0, _Tuples...>
931{
932};
933
934template <class _Types, class _I0, class _J0>
935struct __tuple_cat;
936
937template <class ..._Types, size_t ..._I0, size_t ..._J0>
938struct __tuple_cat<tuple<_Types...>, __tuple_indices<_I0...>, __tuple_indices<_J0...> >
939{
940    template <class _Tuple0>
941    _LIBCPP_INLINE_VISIBILITY
942    typename __tuple_cat_return_ref<tuple<_Types...>&&, _Tuple0&&>::type
943    operator()(tuple<_Types...> __t, _Tuple0&& __t0)
944    {
945        return _VSTD::forward_as_tuple(_VSTD::forward<_Types>(get<_I0>(__t))...,
946                                      get<_J0>(_VSTD::forward<_Tuple0>(__t0))...);
947    }
948
949    template <class _Tuple0, class _Tuple1, class ..._Tuples>
950    _LIBCPP_INLINE_VISIBILITY
951    typename __tuple_cat_return_ref<tuple<_Types...>&&, _Tuple0&&, _Tuple1&&, _Tuples&&...>::type
952    operator()(tuple<_Types...> __t, _Tuple0&& __t0, _Tuple1&& __t1, _Tuples&& ...__tpls)
953    {
954        typedef typename remove_reference<_Tuple0>::type _T0;
955        typedef typename remove_reference<_Tuple1>::type _T1;
956        return __tuple_cat<
957           tuple<_Types..., typename __apply_cv<_Tuple0, typename tuple_element<_J0, _T0>::type>::type&&...>,
958           typename __make_tuple_indices<sizeof ...(_Types) + tuple_size<_T0>::value>::type,
959           typename __make_tuple_indices<tuple_size<_T1>::value>::type>()
960                           (_VSTD::forward_as_tuple(
961                              _VSTD::forward<_Types>(get<_I0>(__t))...,
962                              get<_J0>(_VSTD::forward<_Tuple0>(__t0))...
963                            ),
964                            _VSTD::forward<_Tuple1>(__t1),
965                            _VSTD::forward<_Tuples>(__tpls)...);
966    }
967};
968
969template <class _Tuple0, class... _Tuples>
970inline _LIBCPP_INLINE_VISIBILITY
971typename __tuple_cat_return<_Tuple0, _Tuples...>::type
972tuple_cat(_Tuple0&& __t0, _Tuples&&... __tpls)
973{
974    typedef typename remove_reference<_Tuple0>::type _T0;
975    return __tuple_cat<tuple<>, __tuple_indices<>,
976                  typename __make_tuple_indices<tuple_size<_T0>::value>::type>()
977                  (tuple<>(), _VSTD::forward<_Tuple0>(__t0),
978                                            _VSTD::forward<_Tuples>(__tpls)...);
979}
980
981template <class ..._Tp, class _Alloc>
982struct _LIBCPP_VISIBLE uses_allocator<tuple<_Tp...>, _Alloc>
983    : true_type {};
984
985template <class _T1, class _T2>
986template <class... _Args1, class... _Args2, size_t ..._I1, size_t ..._I2>
987inline _LIBCPP_INLINE_VISIBILITY
988pair<_T1, _T2>::pair(piecewise_construct_t,
989                     tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
990                     __tuple_indices<_I1...>, __tuple_indices<_I2...>)
991    :  first(_VSTD::forward<_Args1>(get<_I1>( __first_args))...),
992      second(_VSTD::forward<_Args2>(get<_I2>(__second_args))...)
993{
994}
995
996#endif  // _LIBCPP_HAS_NO_VARIADICS
997
998_LIBCPP_END_NAMESPACE_STD
999
1000#endif  // _LIBCPP_TUPLE
1001