xref: /llvm-project-15.0.7/libcxx/include/tuple (revision a9538778)
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 <memory>
120#include <type_traits>
121
122#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
123#pragma GCC system_header
124#endif
125
126_LIBCPP_BEGIN_NAMESPACE_STD
127
128#ifndef _LIBCPP_HAS_NO_VARIADICS
129
130// tuple_size
131
132template <class ..._Tp>
133class _LIBCPP_VISIBLE tuple_size<tuple<_Tp...> >
134    : public integral_constant<size_t, sizeof...(_Tp)>
135{
136};
137
138// tuple_element
139
140template <size_t _Ip, class ..._Tp>
141class _LIBCPP_VISIBLE tuple_element<_Ip, tuple<_Tp...> >
142{
143public:
144    typedef typename tuple_element<_Ip, __tuple_types<_Tp...> >::type type;
145};
146
147// __tuple_leaf
148
149template <size_t _Ip, class _Hp, bool=is_empty<_Hp>::value
150#if __has_feature(is_final)
151                                 && !__is_final(_Hp)
152#endif
153         >
154class __tuple_leaf;
155
156template <size_t _Ip, class _Hp, bool _Ep>
157inline _LIBCPP_INLINE_VISIBILITY
158void swap(__tuple_leaf<_Ip, _Hp, _Ep>& __x, __tuple_leaf<_Ip, _Hp, _Ep>& __y)
159    _NOEXCEPT_(__is_nothrow_swappable<_Hp>::value)
160{
161    swap(__x.get(), __y.get());
162}
163
164template <size_t _Ip, class _Hp, bool>
165class __tuple_leaf
166{
167    _Hp value;
168
169    __tuple_leaf& operator=(const __tuple_leaf&);
170public:
171    _LIBCPP_INLINE_VISIBILITY __tuple_leaf() : value()
172       {static_assert(!is_reference<_Hp>::value,
173              "Attempted to default construct a reference element in a tuple");}
174
175    template <class _Alloc>
176        _LIBCPP_INLINE_VISIBILITY
177        __tuple_leaf(integral_constant<int, 0>, const _Alloc&)
178            : value()
179        {static_assert(!is_reference<_Hp>::value,
180              "Attempted to default construct a reference element in a tuple");}
181
182    template <class _Alloc>
183        _LIBCPP_INLINE_VISIBILITY
184        __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
185            : value(allocator_arg_t(), __a)
186        {static_assert(!is_reference<_Hp>::value,
187              "Attempted to default construct a reference element in a tuple");}
188
189    template <class _Alloc>
190        _LIBCPP_INLINE_VISIBILITY
191        __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a)
192            : value(__a)
193        {static_assert(!is_reference<_Hp>::value,
194              "Attempted to default construct a reference element in a tuple");}
195
196    template <class _Tp,
197              class = typename enable_if<is_constructible<_Hp, _Tp>::value>::type>
198        _LIBCPP_INLINE_VISIBILITY
199        explicit __tuple_leaf(_Tp&& __t)
200            : value(_VSTD::forward<_Tp>(__t))
201        {static_assert(!is_reference<_Hp>::value ||
202                       (is_lvalue_reference<_Hp>::value &&
203                        (is_lvalue_reference<_Tp>::value ||
204                         is_same<typename remove_reference<_Tp>::type,
205                                 reference_wrapper<
206                                    typename remove_reference<_Hp>::type
207                                 >
208                                >::value)) ||
209                        (is_rvalue_reference<_Hp>::value &&
210                         !is_lvalue_reference<_Tp>::value),
211       "Attempted to construct a reference element in a tuple with an rvalue");}
212
213    template <class _Tp, class _Alloc>
214        _LIBCPP_INLINE_VISIBILITY
215        explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
216            : value(_VSTD::forward<_Tp>(__t))
217        {static_assert(!is_lvalue_reference<_Hp>::value ||
218                       (is_lvalue_reference<_Hp>::value &&
219                        (is_lvalue_reference<_Tp>::value ||
220                         is_same<typename remove_reference<_Tp>::type,
221                                 reference_wrapper<
222                                    typename remove_reference<_Hp>::type
223                                 >
224                                >::value)),
225       "Attempted to construct a reference element in a tuple with an rvalue");}
226
227    template <class _Tp, class _Alloc>
228        _LIBCPP_INLINE_VISIBILITY
229        explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
230            : value(allocator_arg_t(), __a, _VSTD::forward<_Tp>(__t))
231        {static_assert(!is_lvalue_reference<_Hp>::value ||
232                       (is_lvalue_reference<_Hp>::value &&
233                        (is_lvalue_reference<_Tp>::value ||
234                         is_same<typename remove_reference<_Tp>::type,
235                                 reference_wrapper<
236                                    typename remove_reference<_Hp>::type
237                                 >
238                                >::value)),
239       "Attempted to construct a reference element in a tuple with an rvalue");}
240
241    template <class _Tp, class _Alloc>
242        _LIBCPP_INLINE_VISIBILITY
243        explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
244            : value(_VSTD::forward<_Tp>(__t), __a)
245        {static_assert(!is_lvalue_reference<_Hp>::value ||
246                       (is_lvalue_reference<_Hp>::value &&
247                        (is_lvalue_reference<_Tp>::value ||
248                         is_same<typename remove_reference<_Tp>::type,
249                                 reference_wrapper<
250                                    typename remove_reference<_Hp>::type
251                                 >
252                                >::value)),
253       "Attempted to construct a reference element in a tuple with an rvalue");}
254
255    __tuple_leaf(const __tuple_leaf& __t)
256        : value(__t.get())
257        {static_assert(!is_rvalue_reference<_Hp>::value, "Can not copy a tuple with rvalue reference member");}
258
259    template <class _Tp>
260        _LIBCPP_INLINE_VISIBILITY
261        explicit __tuple_leaf(const __tuple_leaf<_Ip, _Tp>& __t)
262            : value(__t.get()) {}
263
264    template <class _Tp>
265        _LIBCPP_INLINE_VISIBILITY
266        __tuple_leaf&
267        operator=(_Tp&& __t)
268        {
269            value = _VSTD::forward<_Tp>(__t);
270            return *this;
271        }
272
273    _LIBCPP_INLINE_VISIBILITY
274    int swap(__tuple_leaf& __t) _NOEXCEPT_(__is_nothrow_swappable<__tuple_leaf>::value)
275    {
276        _VSTD::swap(*this, __t);
277        return 0;
278    }
279
280    _LIBCPP_INLINE_VISIBILITY       _Hp& get()       {return value;}
281    _LIBCPP_INLINE_VISIBILITY const _Hp& get() const {return value;}
282};
283
284template <size_t _Ip, class _Hp>
285class __tuple_leaf<_Ip, _Hp, true>
286    : private _Hp
287{
288
289    __tuple_leaf& operator=(const __tuple_leaf&);
290public:
291    _LIBCPP_INLINE_VISIBILITY __tuple_leaf() {}
292
293    template <class _Alloc>
294        _LIBCPP_INLINE_VISIBILITY
295        __tuple_leaf(integral_constant<int, 0>, const _Alloc&) {}
296
297    template <class _Alloc>
298        _LIBCPP_INLINE_VISIBILITY
299        __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
300            : _Hp(allocator_arg_t(), __a) {}
301
302    template <class _Alloc>
303        _LIBCPP_INLINE_VISIBILITY
304        __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a)
305            : _Hp(__a) {}
306
307    template <class _Tp,
308              class = typename enable_if<is_constructible<_Hp, _Tp>::value>::type>
309        _LIBCPP_INLINE_VISIBILITY
310        explicit __tuple_leaf(_Tp&& __t)
311            : _Hp(_VSTD::forward<_Tp>(__t)) {}
312
313    template <class _Tp, class _Alloc>
314        _LIBCPP_INLINE_VISIBILITY
315        explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
316            : _Hp(_VSTD::forward<_Tp>(__t)) {}
317
318    template <class _Tp, class _Alloc>
319        _LIBCPP_INLINE_VISIBILITY
320        explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
321            : _Hp(allocator_arg_t(), __a, _VSTD::forward<_Tp>(__t)) {}
322
323    template <class _Tp, class _Alloc>
324        _LIBCPP_INLINE_VISIBILITY
325        explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
326            : _Hp(_VSTD::forward<_Tp>(__t), __a) {}
327
328    template <class _Tp>
329        _LIBCPP_INLINE_VISIBILITY
330        explicit __tuple_leaf(const __tuple_leaf<_Ip, _Tp>& __t)
331            : _Hp(__t.get()) {}
332
333    template <class _Tp>
334        _LIBCPP_INLINE_VISIBILITY
335        __tuple_leaf&
336        operator=(_Tp&& __t)
337        {
338            _Hp::operator=(_VSTD::forward<_Tp>(__t));
339            return *this;
340        }
341
342    _LIBCPP_INLINE_VISIBILITY
343    int
344    swap(__tuple_leaf& __t) _NOEXCEPT_(__is_nothrow_swappable<__tuple_leaf>::value)
345    {
346        _VSTD::swap(*this, __t);
347        return 0;
348    }
349
350    _LIBCPP_INLINE_VISIBILITY       _Hp& get()       {return static_cast<_Hp&>(*this);}
351    _LIBCPP_INLINE_VISIBILITY const _Hp& get() const {return static_cast<const _Hp&>(*this);}
352};
353
354template <class ..._Tp>
355_LIBCPP_INLINE_VISIBILITY
356void __swallow(_Tp&&...) {}
357
358template <bool ...> struct __all;
359
360template <>
361struct __all<>
362{
363    static const bool value = true;
364};
365
366template <bool _B0, bool ... _Bp>
367struct __all<_B0, _Bp...>
368{
369    static const bool value = _B0 && __all<_Bp...>::value;
370};
371
372// __tuple_impl
373
374template<class _Indx, class ..._Tp> struct __tuple_impl;
375
376template<size_t ..._Indx, class ..._Tp>
377struct __tuple_impl<__tuple_indices<_Indx...>, _Tp...>
378    : public __tuple_leaf<_Indx, _Tp>...
379{
380    template <size_t ..._Uf, class ..._Tf,
381              size_t ..._Ul, class ..._Tl, class ..._Up>
382        _LIBCPP_INLINE_VISIBILITY
383        explicit
384        __tuple_impl(__tuple_indices<_Uf...>, __tuple_types<_Tf...>,
385                     __tuple_indices<_Ul...>, __tuple_types<_Tl...>,
386                     _Up&&... __u) :
387            __tuple_leaf<_Uf, _Tf>(_VSTD::forward<_Up>(__u))...,
388            __tuple_leaf<_Ul, _Tl>()...
389            {}
390
391    template <class _Alloc, size_t ..._Uf, class ..._Tf,
392              size_t ..._Ul, class ..._Tl, class ..._Up>
393        _LIBCPP_INLINE_VISIBILITY
394        explicit
395        __tuple_impl(allocator_arg_t, const _Alloc& __a,
396                     __tuple_indices<_Uf...>, __tuple_types<_Tf...>,
397                     __tuple_indices<_Ul...>, __tuple_types<_Tl...>,
398                     _Up&&... __u) :
399            __tuple_leaf<_Uf, _Tf>(__uses_alloc_ctor<_Tf, _Alloc, _Up>(), __a,
400            _VSTD::forward<_Up>(__u))...,
401            __tuple_leaf<_Ul, _Tl>(__uses_alloc_ctor<_Tl, _Alloc>(), __a)...
402            {}
403
404    template <class _Tuple,
405              class = typename enable_if
406                      <
407                         __tuple_convertible<_Tuple, tuple<_Tp...> >::value
408                      >::type
409             >
410        _LIBCPP_INLINE_VISIBILITY
411        __tuple_impl(_Tuple&& __t)
412            : __tuple_leaf<_Indx, _Tp>(_VSTD::forward<typename tuple_element<_Indx,
413                                       typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<_Indx>(__t)))...
414            {}
415
416    template <class _Alloc, class _Tuple,
417              class = typename enable_if
418                      <
419                         __tuple_convertible<_Tuple, tuple<_Tp...> >::value
420                      >::type
421             >
422        _LIBCPP_INLINE_VISIBILITY
423        __tuple_impl(allocator_arg_t, const _Alloc& __a, _Tuple&& __t)
424            : __tuple_leaf<_Indx, _Tp>(__uses_alloc_ctor<_Tp, _Alloc, typename tuple_element<_Indx,
425                                       typename __make_tuple_types<_Tuple>::type>::type>(), __a,
426                                       _VSTD::forward<typename tuple_element<_Indx,
427                                       typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<_Indx>(__t)))...
428            {}
429
430    template <class _Tuple>
431        _LIBCPP_INLINE_VISIBILITY
432        typename enable_if
433        <
434            __tuple_assignable<_Tuple, tuple<_Tp...> >::value,
435            __tuple_impl&
436        >::type
437        operator=(_Tuple&& __t)
438        {
439            __swallow(__tuple_leaf<_Indx, _Tp>::operator=(_VSTD::forward<typename tuple_element<_Indx,
440                                       typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<_Indx>(__t)))...);
441            return *this;
442        }
443
444    _LIBCPP_INLINE_VISIBILITY
445    void swap(__tuple_impl& __t)
446        _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
447    {
448        __swallow(__tuple_leaf<_Indx, _Tp>::swap(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t))...);
449    }
450};
451
452template <class ..._Tp>
453class _LIBCPP_VISIBLE tuple
454{
455    typedef __tuple_impl<typename __make_tuple_indices<sizeof...(_Tp)>::type, _Tp...> base;
456
457    base base_;
458
459    template <size_t _Jp, class ..._Up> friend
460        typename tuple_element<_Jp, tuple<_Up...> >::type& get(tuple<_Up...>&) _NOEXCEPT;
461    template <size_t _Jp, class ..._Up> friend
462        const typename tuple_element<_Jp, tuple<_Up...> >::type& get(const tuple<_Up...>&) _NOEXCEPT;
463    template <size_t _Jp, class ..._Up> friend
464        typename tuple_element<_Jp, tuple<_Up...> >::type&& get(tuple<_Up...>&&) _NOEXCEPT;
465public:
466
467    _LIBCPP_INLINE_VISIBILITY
468    explicit tuple(const _Tp& ... __t)
469        : base_(typename __make_tuple_indices<sizeof...(_Tp)>::type(),
470                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
471                typename __make_tuple_indices<0>::type(),
472                typename __make_tuple_types<tuple, 0>::type(),
473                __t...
474               ) {}
475
476    template <class _Alloc>
477      _LIBCPP_INLINE_VISIBILITY
478      tuple(allocator_arg_t, const _Alloc& __a, const _Tp& ... __t)
479        : base_(allocator_arg_t(), __a,
480                typename __make_tuple_indices<sizeof...(_Tp)>::type(),
481                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
482                typename __make_tuple_indices<0>::type(),
483                typename __make_tuple_types<tuple, 0>::type(),
484                __t...
485               ) {}
486
487    template <class ..._Up,
488              class = typename enable_if
489                      <
490                         sizeof...(_Up) <= sizeof...(_Tp) &&
491                         __tuple_convertible
492                         <
493                            tuple<_Up...>,
494                            typename __make_tuple_types<tuple,
495                                     sizeof...(_Up) < sizeof...(_Tp) ?
496                                        sizeof...(_Up) :
497                                        sizeof...(_Tp)>::type
498                         >::value
499                      >::type
500             >
501        _LIBCPP_INLINE_VISIBILITY
502        explicit
503        tuple(_Up&&... __u)
504            : base_(typename __make_tuple_indices<sizeof...(_Up)>::type(),
505                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
506                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
507                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
508                    _VSTD::forward<_Up>(__u)...) {}
509
510    template <class _Alloc, class ..._Up,
511              class = typename enable_if
512                      <
513                         sizeof...(_Up) <= sizeof...(_Tp) &&
514                         __tuple_convertible
515                         <
516                            tuple<_Up...>,
517                            typename __make_tuple_types<tuple,
518                                     sizeof...(_Up) < sizeof...(_Tp) ?
519                                        sizeof...(_Up) :
520                                        sizeof...(_Tp)>::type
521                         >::value
522                      >::type
523             >
524        _LIBCPP_INLINE_VISIBILITY
525        tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u)
526            : base_(allocator_arg_t(), __a,
527                    typename __make_tuple_indices<sizeof...(_Up)>::type(),
528                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
529                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
530                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
531                    _VSTD::forward<_Up>(__u)...) {}
532
533    template <class _Tuple,
534              class = typename enable_if
535                      <
536                         __tuple_convertible<_Tuple, tuple>::value
537                      >::type
538             >
539        _LIBCPP_INLINE_VISIBILITY
540        tuple(_Tuple&& __t)
541            : base_(_VSTD::forward<_Tuple>(__t)) {}
542
543    template <class _Alloc, class _Tuple,
544              class = typename enable_if
545                      <
546                         __tuple_convertible<_Tuple, tuple>::value
547                      >::type
548             >
549        _LIBCPP_INLINE_VISIBILITY
550        tuple(allocator_arg_t, const _Alloc& __a, _Tuple&& __t)
551            : base_(allocator_arg_t(), __a, _VSTD::forward<_Tuple>(__t)) {}
552
553    template <class _Tuple,
554              class = typename enable_if
555                      <
556                         __tuple_assignable<_Tuple, tuple>::value
557                      >::type
558             >
559        _LIBCPP_INLINE_VISIBILITY
560        tuple&
561        operator=(_Tuple&& __t)
562        {
563            base_.operator=(_VSTD::forward<_Tuple>(__t));
564            return *this;
565        }
566
567    _LIBCPP_INLINE_VISIBILITY
568    void swap(tuple& __t) _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
569        {base_.swap(__t.base_);}
570};
571
572template <>
573class _LIBCPP_VISIBLE tuple<>
574{
575public:
576    _LIBCPP_INLINE_VISIBILITY
577    tuple() {}
578    template <class _Alloc>
579    _LIBCPP_INLINE_VISIBILITY
580        tuple(allocator_arg_t, const _Alloc&) {}
581    template <class _Alloc>
582    _LIBCPP_INLINE_VISIBILITY
583        tuple(allocator_arg_t, const _Alloc&, const tuple&) {}
584    template <class _Up>
585    _LIBCPP_INLINE_VISIBILITY
586        tuple(array<_Up, 0>) {}
587    template <class _Alloc, class _Up>
588    _LIBCPP_INLINE_VISIBILITY
589        tuple(allocator_arg_t, const _Alloc&, array<_Up, 0>) {}
590    _LIBCPP_INLINE_VISIBILITY
591    void swap(tuple&) _NOEXCEPT {}
592};
593
594template <class ..._Tp>
595inline _LIBCPP_INLINE_VISIBILITY
596typename enable_if
597<
598    __all<__is_swappable<_Tp>::value...>::value,
599    void
600>::type
601swap(tuple<_Tp...>& __t, tuple<_Tp...>& __u)
602                 _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
603    {__t.swap(__u);}
604
605// get
606
607template <size_t _Ip, class ..._Tp>
608inline _LIBCPP_INLINE_VISIBILITY
609typename tuple_element<_Ip, tuple<_Tp...> >::type&
610get(tuple<_Tp...>& __t) _NOEXCEPT
611{
612    typedef typename tuple_element<_Ip, tuple<_Tp...> >::type type;
613    return static_cast<__tuple_leaf<_Ip, type>&>(__t.base_).get();
614}
615
616template <size_t _Ip, class ..._Tp>
617inline _LIBCPP_INLINE_VISIBILITY
618const typename tuple_element<_Ip, tuple<_Tp...> >::type&
619get(const tuple<_Tp...>& __t) _NOEXCEPT
620{
621    typedef typename tuple_element<_Ip, tuple<_Tp...> >::type type;
622    return static_cast<const __tuple_leaf<_Ip, type>&>(__t.base_).get();
623}
624
625template <size_t _Ip, class ..._Tp>
626inline _LIBCPP_INLINE_VISIBILITY
627typename tuple_element<_Ip, tuple<_Tp...> >::type&&
628get(tuple<_Tp...>&& __t) _NOEXCEPT
629{
630    typedef typename tuple_element<_Ip, tuple<_Tp...> >::type type;
631    return static_cast<type&&>(
632             static_cast<__tuple_leaf<_Ip, type>&&>(__t.base_).get());
633}
634
635// tie
636
637template <class ..._Tp>
638inline _LIBCPP_INLINE_VISIBILITY
639tuple<_Tp&...>
640tie(_Tp&... __t)
641{
642    return tuple<_Tp&...>(__t...);
643}
644
645template <class _Up>
646struct __ignore_t
647{
648    template <class _Tp>
649        _LIBCPP_INLINE_VISIBILITY
650        const __ignore_t& operator=(_Tp&&) const {return *this;}
651};
652
653namespace { const __ignore_t<unsigned char> ignore = __ignore_t<unsigned char>(); }
654
655template <class _Tp> class reference_wrapper;
656
657template <class _Tp>
658struct ___make_tuple_return
659{
660    typedef _Tp type;
661};
662
663template <class _Tp>
664struct ___make_tuple_return<reference_wrapper<_Tp> >
665{
666    typedef _Tp& type;
667};
668
669template <class _Tp>
670struct __make_tuple_return
671{
672    typedef typename ___make_tuple_return<typename decay<_Tp>::type>::type type;
673};
674
675template <class... _Tp>
676inline _LIBCPP_INLINE_VISIBILITY
677tuple<typename __make_tuple_return<_Tp>::type...>
678make_tuple(_Tp&&... __t)
679{
680    return tuple<typename __make_tuple_return<_Tp>::type...>(_VSTD::forward<_Tp>(__t)...);
681}
682
683template <class... _Tp>
684inline _LIBCPP_INLINE_VISIBILITY
685tuple<_Tp&&...>
686forward_as_tuple(_Tp&&... __t)
687{
688    return tuple<_Tp&&...>(_VSTD::forward<_Tp>(__t)...);
689}
690
691template <size_t _Ip>
692struct __tuple_equal
693{
694    template <class _Tp, class _Up>
695    _LIBCPP_INLINE_VISIBILITY
696    bool operator()(const _Tp& __x, const _Up& __y)
697    {
698        return __tuple_equal<_Ip - 1>()(__x, __y) && get<_Ip-1>(__x) == get<_Ip-1>(__y);
699    }
700};
701
702template <>
703struct __tuple_equal<0>
704{
705    template <class _Tp, class _Up>
706    _LIBCPP_INLINE_VISIBILITY
707    bool operator()(const _Tp&, const _Up&)
708    {
709        return true;
710    }
711};
712
713template <class ..._Tp, class ..._Up>
714inline _LIBCPP_INLINE_VISIBILITY
715bool
716operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
717{
718    return __tuple_equal<sizeof...(_Tp)>()(__x, __y);
719}
720
721template <class ..._Tp, class ..._Up>
722inline _LIBCPP_INLINE_VISIBILITY
723bool
724operator!=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
725{
726    return !(__x == __y);
727}
728
729template <size_t _Ip>
730struct __tuple_less
731{
732    template <class _Tp, class _Up>
733    _LIBCPP_INLINE_VISIBILITY
734    bool operator()(const _Tp& __x, const _Up& __y)
735    {
736        return __tuple_less<_Ip-1>()(__x, __y) ||
737             (!__tuple_less<_Ip-1>()(__y, __x) && get<_Ip-1>(__x) < get<_Ip-1>(__y));
738    }
739};
740
741template <>
742struct __tuple_less<0>
743{
744    template <class _Tp, class _Up>
745    _LIBCPP_INLINE_VISIBILITY
746    bool operator()(const _Tp&, const _Up&)
747    {
748        return false;
749    }
750};
751
752template <class ..._Tp, class ..._Up>
753inline _LIBCPP_INLINE_VISIBILITY
754bool
755operator<(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
756{
757    return __tuple_less<sizeof...(_Tp)>()(__x, __y);
758}
759
760template <class ..._Tp, class ..._Up>
761inline _LIBCPP_INLINE_VISIBILITY
762bool
763operator>(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
764{
765    return __y < __x;
766}
767
768template <class ..._Tp, class ..._Up>
769inline _LIBCPP_INLINE_VISIBILITY
770bool
771operator>=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
772{
773    return !(__x < __y);
774}
775
776template <class ..._Tp, class ..._Up>
777inline _LIBCPP_INLINE_VISIBILITY
778bool
779operator<=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
780{
781    return !(__y < __x);
782}
783
784// tuple_cat
785
786template <class _Tp, class _Up> struct __tuple_cat_type;
787
788template <class ..._Ttypes, class ..._Utypes>
789struct __tuple_cat_type<tuple<_Ttypes...>, __tuple_types<_Utypes...> >
790{
791    typedef tuple<_Ttypes..., _Utypes...> type;
792};
793
794template <class _ResultTuple, bool _Is_Tuple0TupleLike, class ..._Tuples>
795struct __tuple_cat_return_1
796{
797};
798
799template <class ..._Types, class _Tuple0>
800struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0>
801{
802    typedef typename __tuple_cat_type<tuple<_Types...>,
803            typename __make_tuple_types<typename remove_reference<_Tuple0>::type>::type>::type
804                                                                           type;
805};
806
807template <class ..._Types, class _Tuple0, class _Tuple1, class ..._Tuples>
808struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0, _Tuple1, _Tuples...>
809    : public __tuple_cat_return_1<
810                 typename __tuple_cat_type<
811                     tuple<_Types...>,
812                     typename __make_tuple_types<typename remove_reference<_Tuple0>::type>::type
813                 >::type,
814                 __tuple_like<typename remove_reference<_Tuple1>::type>::value,
815                 _Tuple1, _Tuples...>
816{
817};
818
819template <class ..._Tuples> struct __tuple_cat_return;
820
821template <class _Tuple0, class ..._Tuples>
822struct __tuple_cat_return<_Tuple0, _Tuples...>
823    : public __tuple_cat_return_1<tuple<>,
824         __tuple_like<typename remove_reference<_Tuple0>::type>::value, _Tuple0,
825                                                                     _Tuples...>
826{
827};
828
829template <>
830struct __tuple_cat_return<>
831{
832    typedef tuple<> type;
833};
834
835inline _LIBCPP_INLINE_VISIBILITY
836tuple<>
837tuple_cat()
838{
839    return tuple<>();
840}
841
842template <class _Rp, class _Indices, class _Tuple0, class ..._Tuples>
843struct __tuple_cat_return_ref_imp;
844
845template <class ..._Types, size_t ..._I0, class _Tuple0>
846struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>, _Tuple0>
847{
848    typedef typename remove_reference<_Tuple0>::type _T0;
849    typedef tuple<_Types..., typename __apply_cv<_Tuple0,
850                          typename tuple_element<_I0, _T0>::type>::type&&...> type;
851};
852
853template <class ..._Types, size_t ..._I0, class _Tuple0, class _Tuple1, class ..._Tuples>
854struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>,
855                                  _Tuple0, _Tuple1, _Tuples...>
856    : public __tuple_cat_return_ref_imp<
857         tuple<_Types..., typename __apply_cv<_Tuple0,
858               typename tuple_element<_I0,
859                  typename remove_reference<_Tuple0>::type>::type>::type&&...>,
860         typename __make_tuple_indices<tuple_size<typename
861                                 remove_reference<_Tuple1>::type>::value>::type,
862         _Tuple1, _Tuples...>
863{
864};
865
866template <class _Tuple0, class ..._Tuples>
867struct __tuple_cat_return_ref
868    : public __tuple_cat_return_ref_imp<tuple<>,
869               typename __make_tuple_indices<
870                        tuple_size<typename remove_reference<_Tuple0>::type>::value
871               >::type, _Tuple0, _Tuples...>
872{
873};
874
875template <class _Types, class _I0, class _J0>
876struct __tuple_cat;
877
878template <class ..._Types, size_t ..._I0, size_t ..._J0>
879struct __tuple_cat<tuple<_Types...>, __tuple_indices<_I0...>, __tuple_indices<_J0...> >
880{
881    template <class _Tuple0>
882    _LIBCPP_INLINE_VISIBILITY
883    typename __tuple_cat_return_ref<tuple<_Types...>&&, _Tuple0&&>::type
884    operator()(tuple<_Types...> __t, _Tuple0&& __t0)
885    {
886        return _VSTD::forward_as_tuple(_VSTD::forward<_Types>(get<_I0>(__t))...,
887                                      get<_J0>(_VSTD::forward<_Tuple0>(__t0))...);
888    }
889
890    template <class _Tuple0, class _Tuple1, class ..._Tuples>
891    _LIBCPP_INLINE_VISIBILITY
892    typename __tuple_cat_return_ref<tuple<_Types...>&&, _Tuple0&&, _Tuple1&&, _Tuples&&...>::type
893    operator()(tuple<_Types...> __t, _Tuple0&& __t0, _Tuple1&& __t1, _Tuples&& ...__tpls)
894    {
895        typedef typename remove_reference<_Tuple0>::type _T0;
896        typedef typename remove_reference<_Tuple1>::type _T1;
897        return __tuple_cat<
898           tuple<_Types..., typename __apply_cv<_Tuple0, typename tuple_element<_J0, _T0>::type>::type&&...>,
899           typename __make_tuple_indices<sizeof ...(_Types) + tuple_size<_T0>::value>::type,
900           typename __make_tuple_indices<tuple_size<_T1>::value>::type>()
901                           (_VSTD::forward_as_tuple(
902                              _VSTD::forward<_Types>(get<_I0>(__t))...,
903                              get<_J0>(_VSTD::forward<_Tuple0>(__t0))...
904                            ),
905                            _VSTD::forward<_Tuple1>(__t1),
906                            _VSTD::forward<_Tuples>(__tpls)...);
907    }
908};
909
910template <class _Tuple0, class... _Tuples>
911inline _LIBCPP_INLINE_VISIBILITY
912typename __tuple_cat_return<_Tuple0, _Tuples...>::type
913tuple_cat(_Tuple0&& __t0, _Tuples&&... __tpls)
914{
915    typedef typename remove_reference<_Tuple0>::type _T0;
916    return __tuple_cat<tuple<>, __tuple_indices<>,
917                  typename __make_tuple_indices<tuple_size<_T0>::value>::type>()
918                  (tuple<>(), _VSTD::forward<_Tuple0>(__t0),
919                                            _VSTD::forward<_Tuples>(__tpls)...);
920}
921
922template <class ..._Tp, class _Alloc>
923struct _LIBCPP_VISIBLE uses_allocator<tuple<_Tp...>, _Alloc>
924    : true_type {};
925
926template <class _T1, class _T2>
927template <class... _Args1, class... _Args2, size_t ..._I1, size_t ..._I2>
928inline _LIBCPP_INLINE_VISIBILITY
929pair<_T1, _T2>::pair(piecewise_construct_t,
930                     tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
931                     __tuple_indices<_I1...>, __tuple_indices<_I2...>)
932    :  first(_VSTD::forward<_Args1>(get<_I1>( __first_args))...),
933      second(_VSTD::forward<_Args2>(get<_I2>(__second_args))...)
934{
935}
936
937#endif  // _LIBCPP_HAS_NO_VARIADICS
938
939_LIBCPP_END_NAMESPACE_STD
940
941#endif  // _LIBCPP_TUPLE
942