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