xref: /llvm-project-15.0.7/libcxx/include/tuple (revision 30fdc8d8)
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&&);
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& operator=(tuple&&);
60    template <class... U>
61        tuple& operator=(const tuple<U...>&);
62    template <class... U>
63        tuple& operator=(tuple<U...>&&);
64    template <class U1, class U2>
65        tuple& operator=(const pair<U1, U2>&); // iff sizeof...(T) == 2
66    template <class U1, class U2>
67        tuple& operator=(pair<U1, U2>&&); //iffsizeof...(T) == 2
68
69    void swap(tuple&);
70};
71
72const unspecified ignore;
73
74template <class... T> tuple<V...>  make_tuple(T&&...);
75template <class... T> tuple<T&...> tie(T&...);
76template <class... T, class... U> tuple<T..., U...> tuple_cat(const tuple<T...>&, const tuple<U...>&);
77template <class... T, class... U> tuple<T..., U...> tuple_cat(tuple<T...>&&, const tuple<U...>&);
78template <class... T, class... U> tuple<T..., U...> tuple_cat(const tuple<T...>&, tuple<U...>&&);
79template <class... T, class... U> tuple<T..., U...> tuple_cat(tuple<T...>&&, tuple<U...>&&);
80
81// 20.4.1.4, tuple helper classes:
82template <class T> class tuple_size; // undefined
83template <class... T> class tuple_size<tuple<T...>>;
84template <intsize_t I, class T> class tuple_element; // undefined
85template <intsize_t I, class... T> class tuple_element<I, tuple<T...>>;
86
87// 20.4.1.5, element access:
88template <intsize_t I, class... T> typename tuple_element<I, tuple<T...>>::type& get(tuple<T...>&);
89template <intsize_t I, class... T> typename tuple_element<I, tuple<T...>>::type const& get(const tuple<T...>&);
90
91// 20.4.1.6, relational operators:
92template<class... T, class... U> bool operator==(const tuple<T...>&, const tuple<U...>&);
93template<class... T, class... U> bool operator<(const tuple<T...>&, const tuple<U...>&);
94template<class... T, class... U> bool operator!=(const tuple<T...>&, const tuple<U...>&);
95template<class... T, class... U> bool operator>(const tuple<T...>&, const tuple<U...>&);
96template<class... T, class... U> bool operator<=(const tuple<T...>&, const tuple<U...>&);
97template<class... T, class... U> bool operator>=(const tuple<T...>&, const tuple<U...>&);
98
99template <class... Types, class Alloc>
100  struct uses_allocator<tuple<Types...>, Alloc>;
101
102template <class... Types>
103  void swap(tuple<Types...>& x, tuple<Types...>& y);
104
105template <class InputIterator>
106  InputIterator begin(const std::tuple<InputIterator, InputIterator>& t);
107
108template <class InputIterator>
109  InputIterator end(const std::tuple<InputIterator, InputIterator>& t);
110
111}  // std
112
113*/
114
115#include <__config>
116#include <__tuple>
117#include <cstddef>
118#include <memory>
119#include <type_traits>
120
121#pragma GCC system_header
122
123_LIBCPP_BEGIN_NAMESPACE_STD
124
125#ifndef _LIBCPP_HAS_NO_VARIADICS
126
127// tuple_size
128
129template <class ..._Tp>
130class tuple_size<tuple<_Tp...>>
131    : public integral_constant<size_t, sizeof...(_Tp)>
132{
133};
134
135template <class ..._Tp>
136class tuple_size<const tuple<_Tp...>>
137    : public integral_constant<size_t, sizeof...(_Tp)>
138{
139};
140
141// tuple_element
142
143template <size_t _Ip, class ..._Tp>
144class tuple_element<_Ip, tuple<_Tp...>>
145{
146public:
147    typedef typename tuple_element<_Ip, __tuple_types<_Tp...>>::type type;
148};
149
150template <size_t _Ip, class ..._Tp>
151class tuple_element<_Ip, const tuple<_Tp...>>
152{
153public:
154    typedef const typename tuple_element<_Ip, __tuple_types<_Tp...>>::type type;
155};
156
157// __tuple_leaf
158
159template <size_t _Ip, class _Hp, bool=is_empty<_Hp>::value>
160class __tuple_leaf;
161
162template <size_t _Ip, class _Hp, bool _Ep>
163inline
164void swap(__tuple_leaf<_Ip, _Hp, _Ep>& __x, __tuple_leaf<_Ip, _Hp, _Ep>& __y)
165{
166    swap(__x.get(), __y.get());
167}
168
169template <size_t _Ip, class _Hp, bool>
170class __tuple_leaf
171{
172    _Hp value;
173
174    __tuple_leaf& operator=(const __tuple_leaf&);
175public:
176    _LIBCPP_INLINE_VISIBILITY __tuple_leaf() : value()
177       {static_assert(!is_reference<_Hp>::value,
178              "Attempted to default construct a reference element in a tuple");}
179
180    template <class _Alloc>
181        _LIBCPP_INLINE_VISIBILITY
182        __tuple_leaf(integral_constant<int, 0>, const _Alloc&)
183            : value()
184        {static_assert(!is_reference<_Hp>::value,
185              "Attempted to default construct a reference element in a tuple");}
186
187    template <class _Alloc>
188        _LIBCPP_INLINE_VISIBILITY
189        __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
190            : value(allocator_arg_t(), __a)
191        {static_assert(!is_reference<_Hp>::value,
192              "Attempted to default construct a reference element in a tuple");}
193
194    template <class _Alloc>
195        _LIBCPP_INLINE_VISIBILITY
196        __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a)
197            : value(__a)
198        {static_assert(!is_reference<_Hp>::value,
199              "Attempted to default construct a reference element in a tuple");}
200
201    template <class _Tp>
202        _LIBCPP_INLINE_VISIBILITY
203        explicit __tuple_leaf(_Tp&& __t)
204            : value(_STD::forward<_Tp>(__t))
205        {static_assert(!is_lvalue_reference<_Hp>::value ||
206                        is_lvalue_reference<_Hp>::value &&
207                        (is_lvalue_reference<_Tp>::value ||
208                         is_same<typename remove_reference<_Tp>::type,
209                                 reference_wrapper<
210                                    typename remove_reference<_Hp>::type
211                                 >
212                                >::value),
213       "Attempted to construct a reference element in a tuple with an rvalue");}
214
215    template <class _Tp, class _Alloc>
216        _LIBCPP_INLINE_VISIBILITY
217        explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
218            : value(_STD::forward<_Tp>(__t))
219        {static_assert(!is_lvalue_reference<_Hp>::value ||
220                        is_lvalue_reference<_Hp>::value &&
221                        (is_lvalue_reference<_Tp>::value ||
222                         is_same<typename remove_reference<_Tp>::type,
223                                 reference_wrapper<
224                                    typename remove_reference<_Hp>::type
225                                 >
226                                >::value),
227       "Attempted to construct a reference element in a tuple with an rvalue");}
228
229    template <class _Tp, class _Alloc>
230        _LIBCPP_INLINE_VISIBILITY
231        explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
232            : value(allocator_arg_t(), __a, _STD::forward<_Tp>(__t))
233        {static_assert(!is_lvalue_reference<_Hp>::value ||
234                        is_lvalue_reference<_Hp>::value &&
235                        (is_lvalue_reference<_Tp>::value ||
236                         is_same<typename remove_reference<_Tp>::type,
237                                 reference_wrapper<
238                                    typename remove_reference<_Hp>::type
239                                 >
240                                >::value),
241       "Attempted to construct a reference element in a tuple with an rvalue");}
242
243    template <class _Tp, class _Alloc>
244        _LIBCPP_INLINE_VISIBILITY
245        explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
246            : value(_STD::forward<_Tp>(__t), __a)
247        {static_assert(!is_lvalue_reference<_Hp>::value ||
248                        is_lvalue_reference<_Hp>::value &&
249                        (is_lvalue_reference<_Tp>::value ||
250                         is_same<typename remove_reference<_Tp>::type,
251                                 reference_wrapper<
252                                    typename remove_reference<_Hp>::type
253                                 >
254                                >::value),
255       "Attempted to construct a reference element in a tuple with an rvalue");}
256
257    template <class _Tp>
258        _LIBCPP_INLINE_VISIBILITY
259        explicit __tuple_leaf(const __tuple_leaf<_Ip, _Tp>& __t)
260            : value(__t.get()) {}
261
262    template <class _Tp>
263        _LIBCPP_INLINE_VISIBILITY
264        __tuple_leaf&
265        operator=(_Tp&& __t)
266        {
267            value = _STD::forward<_Tp>(__t);
268            return *this;
269        }
270
271    _LIBCPP_INLINE_VISIBILITY
272    int swap(__tuple_leaf& __t)
273    {
274        _STD::swap(*this, __t);
275        return 0;
276    }
277
278    _LIBCPP_INLINE_VISIBILITY       _Hp& get()       {return value;}
279    _LIBCPP_INLINE_VISIBILITY const _Hp& get() const {return value;}
280};
281
282template <size_t _Ip, class _Hp>
283class __tuple_leaf<_Ip, _Hp, true>
284    : private _Hp
285{
286
287    __tuple_leaf& operator=(const __tuple_leaf&);
288public:
289    _LIBCPP_INLINE_VISIBILITY __tuple_leaf() {}
290
291    template <class _Alloc>
292        _LIBCPP_INLINE_VISIBILITY
293        __tuple_leaf(integral_constant<int, 0>, const _Alloc&) {}
294
295    template <class _Alloc>
296        _LIBCPP_INLINE_VISIBILITY
297        __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
298            : _Hp(allocator_arg_t(), __a) {}
299
300    template <class _Alloc>
301        _LIBCPP_INLINE_VISIBILITY
302        __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a)
303            : _Hp(__a) {}
304
305    template <class _Tp>
306        _LIBCPP_INLINE_VISIBILITY
307        explicit __tuple_leaf(_Tp&& __t)
308            : _Hp(_STD::forward<_Tp>(__t)) {}
309
310    template <class _Tp, class _Alloc>
311        _LIBCPP_INLINE_VISIBILITY
312        explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
313            : _Hp(_STD::forward<_Tp>(__t)) {}
314
315    template <class _Tp, class _Alloc>
316        _LIBCPP_INLINE_VISIBILITY
317        explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
318            : _Hp(allocator_arg_t(), __a, _STD::forward<_Tp>(__t)) {}
319
320    template <class _Tp, class _Alloc>
321        _LIBCPP_INLINE_VISIBILITY
322        explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
323            : _Hp(_STD::forward<_Tp>(__t), __a) {}
324
325    template <class _Tp>
326        _LIBCPP_INLINE_VISIBILITY
327        explicit __tuple_leaf(const __tuple_leaf<_Ip, _Tp>& __t)
328            : _Hp(__t.get()) {}
329
330    template <class _Tp>
331        _LIBCPP_INLINE_VISIBILITY
332        __tuple_leaf&
333        operator=(_Tp&& __t)
334        {
335            _Hp::operator=(_STD::forward<_Tp>(__t));
336            return *this;
337        }
338
339    _LIBCPP_INLINE_VISIBILITY int swap(__tuple_leaf& __t)
340    {
341        _STD::swap(*this, __t);
342        return 0;
343    }
344
345    _LIBCPP_INLINE_VISIBILITY       _Hp& get()       {return static_cast<_Hp&>(*this);}
346    _LIBCPP_INLINE_VISIBILITY const _Hp& get() const {return static_cast<const _Hp&>(*this);}
347};
348
349template <class ..._Tp> void __swallow(_Tp&&...) {}
350
351// __tuple_impl
352
353template<class _Indx, class ..._Tp> struct __tuple_impl;
354
355template<size_t ..._Indx, class ..._Tp>
356struct __tuple_impl<__tuple_indices<_Indx...>, _Tp...>
357    : public __tuple_leaf<_Indx, _Tp>...
358{
359    template <size_t ..._Uf, class ..._Tf,
360              size_t ..._Ul, class ..._Tl, class ..._Up>
361        explicit
362        __tuple_impl(__tuple_indices<_Uf...>, __tuple_types<_Tf...>,
363                     __tuple_indices<_Ul...>, __tuple_types<_Tl...>,
364                     _Up&&... __u) :
365            __tuple_leaf<_Uf, _Tf>(_STD::forward<_Up>(__u))...,
366            __tuple_leaf<_Ul, _Tl>()...
367            {}
368
369    template <class _Alloc, size_t ..._Uf, class ..._Tf,
370              size_t ..._Ul, class ..._Tl, class ..._Up>
371        explicit
372        __tuple_impl(allocator_arg_t, const _Alloc& __a,
373                     __tuple_indices<_Uf...>, __tuple_types<_Tf...>,
374                     __tuple_indices<_Ul...>, __tuple_types<_Tl...>,
375                     _Up&&... __u) :
376            __tuple_leaf<_Uf, _Tf>(__uses_alloc_ctor<_Tf, _Alloc, _Up>(), __a,
377            _STD::forward<_Up>(__u))...,
378            __tuple_leaf<_Ul, _Tl>(__uses_alloc_ctor<_Tl, _Alloc>(), __a)...
379            {}
380
381    template <class _Tuple,
382              class = typename enable_if
383                      <
384                         __tuple_convertible<_Tuple, tuple<_Tp...>>::value
385                      >::type
386             >
387        __tuple_impl(_Tuple&& __t)
388            : __tuple_leaf<_Indx, _Tp>(_STD::forward<typename tuple_element<_Indx,
389                                       typename __make_tuple_types<_Tuple>::type>::type>(_STD::get<_Indx>(__t)))...
390            {}
391
392    template <class _Alloc, class _Tuple,
393              class = typename enable_if
394                      <
395                         __tuple_convertible<_Tuple, tuple<_Tp...>>::value
396                      >::type
397             >
398        __tuple_impl(allocator_arg_t, const _Alloc& __a, _Tuple&& __t)
399            : __tuple_leaf<_Indx, _Tp>(__uses_alloc_ctor<_Tp, _Alloc, typename tuple_element<_Indx,
400                                       typename __make_tuple_types<_Tuple>::type>::type>(), __a,
401                                       _STD::forward<typename tuple_element<_Indx,
402                                       typename __make_tuple_types<_Tuple>::type>::type>(_STD::get<_Indx>(__t)))...
403            {}
404
405    template <class _Tuple>
406        typename enable_if
407        <
408            __tuple_assignable<_Tuple, tuple<_Tp...>>::value,
409            __tuple_impl&
410        >::type
411        operator=(_Tuple&& __t)
412        {
413            __swallow(__tuple_leaf<_Indx, _Tp>::operator=(_STD::forward<typename tuple_element<_Indx,
414                                       typename __make_tuple_types<_Tuple>::type>::type>(_STD::get<_Indx>(__t)))...);
415            return *this;
416        }
417
418    void swap(__tuple_impl& __t)
419    {
420        __swallow(__tuple_leaf<_Indx, _Tp>::swap(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t))...);
421    }
422};
423
424template <class ..._Tp>
425class tuple
426{
427    typedef __tuple_impl<typename __make_tuple_indices<sizeof...(_Tp)>::type, _Tp...> base;
428
429    base base_;
430
431    template <size_t _Jp, class ..._Up> friend
432        typename tuple_element<_Jp, tuple<_Up...>>::type& get(tuple<_Up...>&);
433    template <size_t _Jp, class ..._Up> friend
434        const typename tuple_element<_Jp, tuple<_Up...>>::type& get(const tuple<_Up...>&);
435public:
436
437    explicit tuple(const _Tp& ... __t)
438        : base_(typename __make_tuple_indices<sizeof...(_Tp)>::type(),
439                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
440                typename __make_tuple_indices<0>::type(),
441                typename __make_tuple_types<tuple, 0>::type(),
442                __t...
443               ) {}
444
445    template <class _Alloc>
446      tuple(allocator_arg_t, const _Alloc& __a, const _Tp& ... __t)
447        : base_(allocator_arg_t(), __a,
448                typename __make_tuple_indices<sizeof...(_Tp)>::type(),
449                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
450                typename __make_tuple_indices<0>::type(),
451                typename __make_tuple_types<tuple, 0>::type(),
452                __t...
453               ) {}
454
455    template <class ..._Up,
456              class = typename enable_if
457                      <
458                         sizeof...(_Up) <= sizeof...(_Tp) &&
459                         __tuple_convertible
460                         <
461                            tuple<_Up...>,
462                            typename __make_tuple_types<tuple,
463                                     sizeof...(_Up) < sizeof...(_Tp) ?
464                                        sizeof...(_Up) :
465                                        sizeof...(_Tp)>::type
466                         >::value
467                      >::type
468             >
469        explicit
470        tuple(_Up&&... __u)
471            : base_(typename __make_tuple_indices<sizeof...(_Up)>::type(),
472                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
473                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
474                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
475                    _STD::forward<_Up>(__u)...) {}
476
477    template <class _Alloc, class ..._Up,
478              class = typename enable_if
479                      <
480                         sizeof...(_Up) <= sizeof...(_Tp) &&
481                         __tuple_convertible
482                         <
483                            tuple<_Up...>,
484                            typename __make_tuple_types<tuple,
485                                     sizeof...(_Up) < sizeof...(_Tp) ?
486                                        sizeof...(_Up) :
487                                        sizeof...(_Tp)>::type
488                         >::value
489                      >::type
490             >
491        tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u)
492            : base_(allocator_arg_t(), __a,
493                    typename __make_tuple_indices<sizeof...(_Up)>::type(),
494                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
495                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
496                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
497                    _STD::forward<_Up>(__u)...) {}
498
499    template <class _Tuple,
500              class = typename enable_if
501                      <
502                         __tuple_convertible<_Tuple, tuple>::value
503                      >::type
504             >
505        tuple(_Tuple&& __t)
506            : base_(_STD::forward<_Tuple>(__t)) {}
507
508    template <class _Alloc, class _Tuple,
509              class = typename enable_if
510                      <
511                         __tuple_convertible<_Tuple, tuple>::value
512                      >::type
513             >
514        tuple(allocator_arg_t, const _Alloc& __a, _Tuple&& __t)
515            : base_(allocator_arg_t(), __a, _STD::forward<_Tuple>(__t)) {}
516
517    template <class _Tuple,
518              class = typename enable_if
519                      <
520                         __tuple_assignable<_Tuple, tuple>::value
521                      >::type
522             >
523        tuple&
524        operator=(_Tuple&& __t)
525        {
526            base_.operator=(_STD::forward<_Tuple>(__t));
527            return *this;
528        }
529
530    void swap(tuple& __t) {base_.swap(__t.base_);}
531};
532
533template <>
534class tuple<>
535{
536public:
537    tuple() {}
538    template <class _Alloc>
539        tuple(allocator_arg_t, const _Alloc&) {}
540    template <class _Alloc>
541        tuple(allocator_arg_t, const _Alloc&, const tuple&) {}
542    template <class _U>
543        tuple(array<_U, 0>) {}
544    template <class _Alloc, class _U>
545        tuple(allocator_arg_t, const _Alloc&, array<_U, 0>) {}
546    void swap(tuple&) {}
547};
548
549template <class ..._Tp>
550inline _LIBCPP_INLINE_VISIBILITY
551void
552swap(tuple<_Tp...>& __t, tuple<_Tp...>& __u) {__t.swap(__u);}
553
554// get
555
556template <size_t _Ip, class ..._Tp>
557inline
558typename tuple_element<_Ip, tuple<_Tp...>>::type&
559get(tuple<_Tp...>& __t)
560{
561    typedef typename tuple_element<_Ip, tuple<_Tp...>>::type type;
562    return static_cast<__tuple_leaf<_Ip, type>&>(__t.base_).get();
563}
564
565template <size_t _Ip, class ..._Tp>
566inline
567const typename tuple_element<_Ip, tuple<_Tp...>>::type&
568get(const tuple<_Tp...>& __t)
569{
570    typedef typename tuple_element<_Ip, tuple<_Tp...>>::type type;
571    return static_cast<const __tuple_leaf<_Ip, type>&>(__t.base_).get();
572}
573
574// tie
575
576template <class ..._Tp>
577inline
578tuple<_Tp&...>
579tie(_Tp&... __t)
580{
581    return tuple<_Tp&...>(__t...);
582}
583
584template <class _Up>
585struct __ignore_t
586{
587    __ignore_t() {}
588    template <class _Tp>
589        __ignore_t(_Tp&&) {}
590    template <class _Tp>
591        const __ignore_t& operator=(_Tp&&) const {return *this;}
592};
593
594namespace { const __ignore_t<unsigned char> ignore = __ignore_t<unsigned char>(); }
595
596template <class _Tp> class reference_wrapper;
597
598template <class _Tp>
599struct ___make_tuple_return
600{
601    typedef _Tp type;
602};
603
604template <class _Tp>
605struct ___make_tuple_return<reference_wrapper<_Tp>>
606{
607    typedef _Tp& type;
608};
609
610template <class _Tp>
611struct __make_tuple_return
612{
613    typedef typename ___make_tuple_return<typename decay<_Tp>::type>::type type;
614};
615
616template <class... _Tp>
617inline
618tuple<typename __make_tuple_return<_Tp>::type...>
619make_tuple(_Tp&&... __t)
620{
621    return tuple<typename __make_tuple_return<_Tp>::type...>(_STD::forward<_Tp>(__t)...);
622}
623
624template <size_t _I>
625struct __tuple_equal
626{
627    template <class _Tp, class _Up>
628    bool operator()(const _Tp& __x, const _Up& __y)
629    {
630        return __tuple_equal<_I - 1>()(__x, __y) && get<_I-1>(__x) == get<_I-1>(__y);
631    }
632};
633
634template <>
635struct __tuple_equal<0>
636{
637    template <class _Tp, class _Up>
638    bool operator()(const _Tp&, const _Up&)
639    {
640        return true;
641    }
642};
643
644template <class ..._Tp, class ..._Up>
645inline
646bool
647operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
648{
649    return __tuple_equal<sizeof...(_Tp)>()(__x, __y);
650}
651
652template <class ..._Tp, class ..._Up>
653inline
654bool
655operator!=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
656{
657    return !(__x == __y);
658}
659
660template <size_t _I>
661struct __tuple_less
662{
663    template <class _Tp, class _Up>
664    bool operator()(const _Tp& __x, const _Up& __y)
665    {
666        return __tuple_less<_I-1>()(__x, __y) ||
667             (!__tuple_less<_I-1>()(__y, __x) && get<_I-1>(__x) < get<_I-1>(__y));
668    }
669};
670
671template <>
672struct __tuple_less<0>
673{
674    template <class _Tp, class _Up>
675    bool operator()(const _Tp&, const _Up&)
676    {
677        return false;
678    }
679};
680
681template <class ..._Tp, class ..._Up>
682inline
683bool
684operator<(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
685{
686    return __tuple_less<sizeof...(_Tp)>()(__x, __y);
687}
688
689template <class ..._Tp, class ..._Up>
690inline
691bool
692operator>(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
693{
694    return __y < __x;
695}
696
697template <class ..._Tp, class ..._Up>
698inline
699bool
700operator>=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
701{
702    return !(__x < __y);
703}
704
705template <class ..._Tp, class ..._Up>
706inline
707bool
708operator<=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
709{
710    return !(__y < __x);
711}
712
713// tuple_cat
714
715template <class... _Tp, size_t ..._I1, class... _Up, size_t ..._I2>
716inline
717tuple<_Tp..., _Up...>
718__tuple_cat(const tuple<_Tp...>& __x, __tuple_indices<_I1...>, const tuple<_Up...>& __y, __tuple_indices<_I2...>)
719{
720    return tuple<_Tp..., _Up...>(get<_I1>(__x)..., get<_I2>(__y)...);
721}
722
723template <class... _Tp, class... _Up>
724inline
725tuple<_Tp..., _Up...>
726tuple_cat(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
727{
728    return __tuple_cat(__x, typename __make_tuple_indices<sizeof...(_Tp)>::type(),
729                       __y, typename __make_tuple_indices<sizeof...(_Up)>::type());
730}
731
732template <class... _Tp, size_t ..._I1, class... _Up, size_t ..._I2>
733inline
734tuple<_Tp..., _Up...>
735__tuple_cat(tuple<_Tp...>&& __x, __tuple_indices<_I1...>, const tuple<_Up...>& __y, __tuple_indices<_I2...>)
736{
737    return tuple<_Tp..., _Up...>(_STD::forward<_Tp>(get<_I1>(__x))..., get<_I2>(__y)...);
738}
739
740template <class... _Tp, class... _Up>
741inline
742tuple<_Tp..., _Up...>
743tuple_cat(tuple<_Tp...>&& __x, const tuple<_Up...>& __y)
744{
745    return __tuple_cat(_STD::move(__x), typename __make_tuple_indices<sizeof...(_Tp)>::type(),
746                       __y, typename __make_tuple_indices<sizeof...(_Up)>::type());
747}
748
749template <class... _Tp, size_t ..._I1, class... _Up, size_t ..._I2>
750inline
751tuple<_Tp..., _Up...>
752__tuple_cat(const tuple<_Tp...>& __x, __tuple_indices<_I1...>, tuple<_Up...>&& __y, __tuple_indices<_I2...>)
753{
754    return tuple<_Tp..., _Up...>(get<_I1>(__x)..., _STD::forward<_Up>(get<_I2>(__y))...);
755}
756
757template <class... _Tp, class... _Up>
758inline
759tuple<_Tp..., _Up...>
760tuple_cat(const tuple<_Tp...>& __x, tuple<_Up...>&& __y)
761{
762    return __tuple_cat(__x, typename __make_tuple_indices<sizeof...(_Tp)>::type(),
763                       _STD::move(__y), typename __make_tuple_indices<sizeof...(_Up)>::type());
764}
765
766template <class... _Tp, size_t ..._I1, class... _Up, size_t ..._I2>
767inline
768tuple<_Tp..., _Up...>
769__tuple_cat(tuple<_Tp...>&& __x, __tuple_indices<_I1...>, tuple<_Up...>&& __y, __tuple_indices<_I2...>)
770{
771    return tuple<_Tp..., _Up...>(_STD::forward<_Tp>(get<_I1>(__x))..., _STD::forward<_Up>(get<_I2>(__y))...);
772}
773
774template <class... _Tp, class... _Up>
775inline
776tuple<_Tp..., _Up...>
777tuple_cat(tuple<_Tp...>&& __x, tuple<_Up...>&& __y)
778{
779    return __tuple_cat(_STD::move(__x), typename __make_tuple_indices<sizeof...(_Tp)>::type(),
780                       _STD::move(__y), typename __make_tuple_indices<sizeof...(_Up)>::type());
781}
782
783template <class ..._Tp, class _Alloc>
784struct uses_allocator<tuple<_Tp...>, _Alloc>
785    : true_type {};
786
787template <class _InputIterator>
788inline
789_InputIterator
790begin(const std::tuple<_InputIterator, _InputIterator>& __t)
791{
792    return get<0>(__t);
793}
794
795template <class _InputIterator>
796inline
797_InputIterator
798end(const std::tuple<_InputIterator, _InputIterator>& __t)
799{
800    return get<1>(__t);
801}
802
803template <class _T1, class _T2>
804template <class... _Args1, class... _Args2, size_t ..._I1, size_t ..._I2>
805inline _LIBCPP_INLINE_VISIBILITY
806pair<_T1, _T2>::pair(piecewise_construct_t,
807                     tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
808                     __tuple_indices<_I1...>, __tuple_indices<_I2...>)
809    :  first(_STD::forward<_Args1>(get<_I1>( __first_args))...),
810      second(_STD::forward<_Args2>(get<_I2>(__second_args))...)
811{
812}
813
814#endif
815
816_LIBCPP_END_NAMESPACE_STD
817
818#endif  // _LIBCPP_TUPLE
819