xref: /llvm-project-15.0.7/libcxx/include/tuple (revision cf6a7c19)
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_TUPLE
11#define _LIBCPP_TUPLE
12
13/*
14    tuple synopsis
15
16namespace std
17{
18
19template <class... T>
20class tuple {
21public:
22    explicit(see-below) constexpr tuple();
23    explicit(see-below) tuple(const T&...);  // constexpr in C++14
24    template <class... U>
25        explicit(see-below) tuple(U&&...);  // constexpr in C++14
26    tuple(const tuple&) = default;
27    tuple(tuple&&) = default;
28    template <class... U>
29        explicit(see-below) tuple(const tuple<U...>&);  // constexpr in C++14
30    template <class... U>
31        explicit(see-below) tuple(tuple<U...>&&);  // constexpr in C++14
32    template <class U1, class U2>
33        explicit(see-below) tuple(const pair<U1, U2>&); // iff sizeof...(T) == 2 // constexpr in C++14
34    template <class U1, class U2>
35        explicit(see-below) tuple(pair<U1, U2>&&); // iff sizeof...(T) == 2  // constexpr in C++14
36
37    // allocator-extended constructors
38    template <class Alloc>
39        tuple(allocator_arg_t, const Alloc& a);
40    template <class Alloc>
41        explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const T&...);          // constexpr in C++20
42    template <class Alloc, class... U>
43        explicit(see-below) tuple(allocator_arg_t, const Alloc& a, U&&...);               // constexpr in C++20
44    template <class Alloc>
45        tuple(allocator_arg_t, const Alloc& a, const tuple&);                             // constexpr in C++20
46    template <class Alloc>
47        tuple(allocator_arg_t, const Alloc& a, tuple&&);                                  // constexpr in C++20
48    template <class Alloc, class... U>
49        explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const tuple<U...>&);   // constexpr in C++20
50    template <class Alloc, class... U>
51        explicit(see-below) tuple(allocator_arg_t, const Alloc& a, tuple<U...>&&);        // constexpr in C++20
52    template <class Alloc, class U1, class U2>
53        explicit(see-below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);  // constexpr in C++20
54    template <class Alloc, class U1, class U2>
55        explicit(see-below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);       // constexpr in C++20
56
57    tuple& operator=(const tuple&);                                                       // constexpr in C++20
58    tuple& operator=(tuple&&) noexcept(is_nothrow_move_assignable_v<T> && ...);           // constexpr in C++20
59    template <class... U>
60        tuple& operator=(const tuple<U...>&);                                             // constexpr in C++20
61    template <class... U>
62        tuple& operator=(tuple<U...>&&);                                                  // constexpr in C++20
63    template <class U1, class U2>
64        tuple& operator=(const pair<U1, U2>&); // iff sizeof...(T) == 2                   // constexpr in C++20
65    template <class U1, class U2>
66        tuple& operator=(pair<U1, U2>&&); // iff sizeof...(T) == 2                        // constexpr in C++20
67
68    template<class U, size_t N>
69        tuple& operator=(array<U, N> const&) // iff sizeof...(T) == N, EXTENSION
70    template<class U, size_t N>
71        tuple& operator=(array<U, N>&&) // iff sizeof...(T) == N, EXTENSION
72
73    void swap(tuple&) noexcept(AND(swap(declval<T&>(), declval<T&>())...));               // constexpr in C++20
74};
75
76
77template<class... TTypes, class... UTypes, template<class> class TQual, template<class> class UQual> // since C++23
78  requires requires { typename tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...>; }
79struct basic_common_reference<tuple<TTypes...>, tuple<UTypes...>, TQual, UQual> {
80  using type = tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...>;
81};
82
83template<class... TTypes, class... UTypes>                                // since C++23
84  requires requires { typename tuple<common_type_t<TTypes, UTypes>...>; }
85struct common_type<tuple<TTypes...>, tuple<UTypes...>> {
86  using type = tuple<common_type_t<TTypes, UTypes>...>;
87};
88
89template <class ...T>
90tuple(T...) -> tuple<T...>;                                         // since C++17
91template <class T1, class T2>
92tuple(pair<T1, T2>) -> tuple<T1, T2>;                               // since C++17
93template <class Alloc, class ...T>
94tuple(allocator_arg_t, Alloc, T...) -> tuple<T...>;                 // since C++17
95template <class Alloc, class T1, class T2>
96tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>;       // since C++17
97template <class Alloc, class ...T>
98tuple(allocator_arg_t, Alloc, tuple<T...>) -> tuple<T...>;          // since C++17
99
100inline constexpr unspecified ignore;
101
102template <class... T> tuple<V...>  make_tuple(T&&...); // constexpr in C++14
103template <class... T> tuple<ATypes...> forward_as_tuple(T&&...) noexcept; // constexpr in C++14
104template <class... T> tuple<T&...> tie(T&...) noexcept; // constexpr in C++14
105template <class... Tuples> tuple<CTypes...> tuple_cat(Tuples&&... tpls); // constexpr in C++14
106
107// [tuple.apply], calling a function with a tuple of arguments:
108template <class F, class Tuple>
109  constexpr decltype(auto) apply(F&& f, Tuple&& t); // C++17
110template <class T, class Tuple>
111  constexpr T make_from_tuple(Tuple&& t); // C++17
112
113// 20.4.1.4, tuple helper classes:
114template <class T> struct tuple_size; // undefined
115template <class... T> struct tuple_size<tuple<T...>>;
116template <class T>
117 inline constexpr size_t tuple_size_v = tuple_size<T>::value; // C++17
118template <size_t I, class T> struct tuple_element; // undefined
119template <size_t I, class... T> struct tuple_element<I, tuple<T...>>;
120template <size_t I, class T>
121  using tuple_element_t = typename tuple_element <I, T>::type; // C++14
122
123// 20.4.1.5, element access:
124template <size_t I, class... T>
125    typename tuple_element<I, tuple<T...>>::type&
126    get(tuple<T...>&) noexcept; // constexpr in C++14
127template <size_t I, class... T>
128    const typename tuple_element<I, tuple<T...>>::type&
129    get(const tuple<T...>&) noexcept; // constexpr in C++14
130template <size_t I, class... T>
131    typename tuple_element<I, tuple<T...>>::type&&
132    get(tuple<T...>&&) noexcept; // constexpr in C++14
133template <size_t I, class... T>
134    const typename tuple_element<I, tuple<T...>>::type&&
135    get(const tuple<T...>&&) noexcept; // constexpr in C++14
136
137template <class T1, class... T>
138    constexpr T1& get(tuple<T...>&) noexcept;  // C++14
139template <class T1, class... T>
140    constexpr const T1& get(const tuple<T...>&) noexcept;   // C++14
141template <class T1, class... T>
142    constexpr T1&& get(tuple<T...>&&) noexcept;   // C++14
143template <class T1, class... T>
144    constexpr const T1&& get(const tuple<T...>&&) noexcept;   // C++14
145
146// 20.4.1.6, relational operators:
147template<class... T, class... U> bool operator==(const tuple<T...>&, const tuple<U...>&); // constexpr in C++14
148template<class... T, class... U> bool operator<(const tuple<T...>&, const tuple<U...>&);  // constexpr in C++14, removed in C++20
149template<class... T, class... U> bool operator!=(const tuple<T...>&, const tuple<U...>&); // constexpr in C++14, removed in C++20
150template<class... T, class... U> bool operator>(const tuple<T...>&, const tuple<U...>&);  // constexpr in C++14, removed in C++20
151template<class... T, class... U> bool operator<=(const tuple<T...>&, const tuple<U...>&); // constexpr in C++14, removed in C++20
152template<class... T, class... U> bool operator>=(const tuple<T...>&, const tuple<U...>&); // constexpr in C++14, removed in C++20
153template<class... T, class... U>
154  constexpr common_comparison_category_t<synth-three-way-result<T, U>...>
155    operator<=>(const tuple<T...>&, const tuple<U...>&);                                  // since C++20
156
157template <class... Types, class Alloc>
158  struct uses_allocator<tuple<Types...>, Alloc>;
159
160template <class... Types>
161  void
162  swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(noexcept(x.swap(y)));
163
164}  // std
165
166*/
167
168#include <__assert> // all public C++ headers provide the assertion handler
169#include <__compare/common_comparison_category.h>
170#include <__compare/synth_three_way.h>
171#include <__config>
172#include <__functional/unwrap_ref.h>
173#include <__memory/allocator_arg_t.h>
174#include <__memory/uses_allocator.h>
175#include <__tuple>
176#include <__utility/forward.h>
177#include <__utility/integer_sequence.h>
178#include <__utility/move.h>
179#include <__utility/pair.h>
180#include <__utility/piecewise_construct.h>
181#include <__utility/swap.h>
182#include <compare>
183#include <cstddef>
184#include <type_traits>
185#include <version>
186
187#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
188#  pragma GCC system_header
189#endif
190
191_LIBCPP_BEGIN_NAMESPACE_STD
192
193#ifndef _LIBCPP_CXX03_LANG
194
195
196// __tuple_leaf
197
198template <size_t _Ip, class _Hp,
199          bool=is_empty<_Hp>::value && !__libcpp_is_final<_Hp>::value
200         >
201class __tuple_leaf;
202
203template <size_t _Ip, class _Hp, bool _Ep>
204inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
205void swap(__tuple_leaf<_Ip, _Hp, _Ep>& __x, __tuple_leaf<_Ip, _Hp, _Ep>& __y)
206    _NOEXCEPT_(__is_nothrow_swappable<_Hp>::value)
207{
208    swap(__x.get(), __y.get());
209}
210
211template <size_t _Ip, class _Hp, bool>
212class __tuple_leaf
213{
214    _Hp __value_;
215
216    template <class _Tp>
217    static constexpr bool __can_bind_reference() {
218#if __has_keyword(__reference_binds_to_temporary)
219      return !__reference_binds_to_temporary(_Hp, _Tp);
220#else
221      return true;
222#endif
223    }
224
225    _LIBCPP_CONSTEXPR_AFTER_CXX11
226    __tuple_leaf& operator=(const __tuple_leaf&);
227public:
228    _LIBCPP_INLINE_VISIBILITY constexpr __tuple_leaf()
229             _NOEXCEPT_(is_nothrow_default_constructible<_Hp>::value) : __value_()
230       {static_assert(!is_reference<_Hp>::value,
231              "Attempted to default construct a reference element in a tuple");}
232
233    template <class _Alloc>
234        _LIBCPP_INLINE_VISIBILITY constexpr
235        __tuple_leaf(integral_constant<int, 0>, const _Alloc&)
236            : __value_()
237        {static_assert(!is_reference<_Hp>::value,
238              "Attempted to default construct a reference element in a tuple");}
239
240    template <class _Alloc>
241        _LIBCPP_INLINE_VISIBILITY constexpr
242        __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
243            : __value_(allocator_arg_t(), __a)
244        {static_assert(!is_reference<_Hp>::value,
245              "Attempted to default construct a reference element in a tuple");}
246
247    template <class _Alloc>
248        _LIBCPP_INLINE_VISIBILITY constexpr
249        __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a)
250            : __value_(__a)
251        {static_assert(!is_reference<_Hp>::value,
252              "Attempted to default construct a reference element in a tuple");}
253
254    template <class _Tp,
255              class = __enable_if_t<
256                  _And<
257                      _IsNotSame<__uncvref_t<_Tp>, __tuple_leaf>,
258                      is_constructible<_Hp, _Tp>
259                    >::value
260                >
261            >
262        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
263        explicit __tuple_leaf(_Tp&& __t) _NOEXCEPT_((is_nothrow_constructible<_Hp, _Tp>::value))
264            : __value_(_VSTD::forward<_Tp>(__t))
265        {static_assert(__can_bind_reference<_Tp&&>(),
266       "Attempted construction of reference element binds to a temporary whose lifetime has ended");}
267
268    template <class _Tp, class _Alloc>
269        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
270        explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
271            : __value_(_VSTD::forward<_Tp>(__t))
272        {static_assert(__can_bind_reference<_Tp&&>(),
273       "Attempted construction of reference element binds to a temporary whose lifetime has ended");}
274
275    template <class _Tp, class _Alloc>
276        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
277        explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
278            : __value_(allocator_arg_t(), __a, _VSTD::forward<_Tp>(__t))
279        {static_assert(!is_reference<_Hp>::value,
280            "Attempted to uses-allocator construct a reference element in a tuple");}
281
282    template <class _Tp, class _Alloc>
283        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
284        explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
285            : __value_(_VSTD::forward<_Tp>(__t), __a)
286        {static_assert(!is_reference<_Hp>::value,
287           "Attempted to uses-allocator construct a reference element in a tuple");}
288
289    __tuple_leaf(const __tuple_leaf& __t) = default;
290    __tuple_leaf(__tuple_leaf&& __t) = default;
291
292    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
293    int swap(__tuple_leaf& __t) _NOEXCEPT_(__is_nothrow_swappable<__tuple_leaf>::value)
294    {
295        _VSTD::swap(*this, __t);
296        return 0;
297    }
298
299    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11       _Hp& get()       _NOEXCEPT {return __value_;}
300    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const _Hp& get() const _NOEXCEPT {return __value_;}
301};
302
303template <size_t _Ip, class _Hp>
304class __tuple_leaf<_Ip, _Hp, true>
305    : private _Hp
306{
307    _LIBCPP_CONSTEXPR_AFTER_CXX11
308    __tuple_leaf& operator=(const __tuple_leaf&);
309public:
310    _LIBCPP_INLINE_VISIBILITY constexpr __tuple_leaf()
311             _NOEXCEPT_(is_nothrow_default_constructible<_Hp>::value) {}
312
313    template <class _Alloc>
314        _LIBCPP_INLINE_VISIBILITY constexpr
315        __tuple_leaf(integral_constant<int, 0>, const _Alloc&) {}
316
317    template <class _Alloc>
318        _LIBCPP_INLINE_VISIBILITY constexpr
319        __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
320            : _Hp(allocator_arg_t(), __a) {}
321
322    template <class _Alloc>
323        _LIBCPP_INLINE_VISIBILITY constexpr
324        __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a)
325            : _Hp(__a) {}
326
327    template <class _Tp,
328              class = __enable_if_t<
329                  _And<
330                    _IsNotSame<__uncvref_t<_Tp>, __tuple_leaf>,
331                    is_constructible<_Hp, _Tp>
332                  >::value
333                >
334            >
335        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
336        explicit __tuple_leaf(_Tp&& __t) _NOEXCEPT_((is_nothrow_constructible<_Hp, _Tp>::value))
337            : _Hp(_VSTD::forward<_Tp>(__t)) {}
338
339    template <class _Tp, class _Alloc>
340        _LIBCPP_INLINE_VISIBILITY constexpr
341        explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
342            : _Hp(_VSTD::forward<_Tp>(__t)) {}
343
344    template <class _Tp, class _Alloc>
345        _LIBCPP_INLINE_VISIBILITY constexpr
346        explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
347            : _Hp(allocator_arg_t(), __a, _VSTD::forward<_Tp>(__t)) {}
348
349    template <class _Tp, class _Alloc>
350        _LIBCPP_INLINE_VISIBILITY constexpr
351        explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
352            : _Hp(_VSTD::forward<_Tp>(__t), __a) {}
353
354    __tuple_leaf(__tuple_leaf const &) = default;
355    __tuple_leaf(__tuple_leaf &&) = default;
356
357    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
358    int
359    swap(__tuple_leaf& __t) _NOEXCEPT_(__is_nothrow_swappable<__tuple_leaf>::value)
360    {
361        _VSTD::swap(*this, __t);
362        return 0;
363    }
364
365    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11       _Hp& get()       _NOEXCEPT {return static_cast<_Hp&>(*this);}
366    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const _Hp& get() const _NOEXCEPT {return static_cast<const _Hp&>(*this);}
367};
368
369template <class ..._Tp>
370_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
371void __swallow(_Tp&&...) _NOEXCEPT {}
372
373template <class _Tp>
374struct __all_default_constructible;
375
376template <class ..._Tp>
377struct __all_default_constructible<__tuple_types<_Tp...>>
378    : __all<is_default_constructible<_Tp>::value...>
379{ };
380
381// __tuple_impl
382
383template<class _Indx, class ..._Tp> struct __tuple_impl;
384
385template<size_t ..._Indx, class ..._Tp>
386struct _LIBCPP_DECLSPEC_EMPTY_BASES __tuple_impl<__tuple_indices<_Indx...>, _Tp...>
387    : public __tuple_leaf<_Indx, _Tp>...
388{
389    _LIBCPP_INLINE_VISIBILITY
390    constexpr __tuple_impl()
391        _NOEXCEPT_(__all<is_nothrow_default_constructible<_Tp>::value...>::value) {}
392
393    template <size_t ..._Uf, class ..._Tf,
394              size_t ..._Ul, class ..._Tl, class ..._Up>
395        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
396        explicit
397        __tuple_impl(__tuple_indices<_Uf...>, __tuple_types<_Tf...>,
398                     __tuple_indices<_Ul...>, __tuple_types<_Tl...>,
399                     _Up&&... __u)
400                     _NOEXCEPT_((__all<is_nothrow_constructible<_Tf, _Up>::value...>::value &&
401                                 __all<is_nothrow_default_constructible<_Tl>::value...>::value)) :
402            __tuple_leaf<_Uf, _Tf>(_VSTD::forward<_Up>(__u))...,
403            __tuple_leaf<_Ul, _Tl>()...
404            {}
405
406    template <class _Alloc, size_t ..._Uf, class ..._Tf,
407              size_t ..._Ul, class ..._Tl, class ..._Up>
408        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
409        explicit
410        __tuple_impl(allocator_arg_t, const _Alloc& __a,
411                     __tuple_indices<_Uf...>, __tuple_types<_Tf...>,
412                     __tuple_indices<_Ul...>, __tuple_types<_Tl...>,
413                     _Up&&... __u) :
414            __tuple_leaf<_Uf, _Tf>(__uses_alloc_ctor<_Tf, _Alloc, _Up>(), __a,
415            _VSTD::forward<_Up>(__u))...,
416            __tuple_leaf<_Ul, _Tl>(__uses_alloc_ctor<_Tl, _Alloc>(), __a)...
417            {}
418
419    template <class _Tuple,
420              class = typename enable_if
421                      <
422                         __tuple_constructible<_Tuple, tuple<_Tp...> >::value
423                      >::type
424             >
425        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
426        __tuple_impl(_Tuple&& __t) _NOEXCEPT_((__all<is_nothrow_constructible<_Tp, typename tuple_element<_Indx,
427                                       typename __make_tuple_types<_Tuple>::type>::type>::value...>::value))
428            : __tuple_leaf<_Indx, _Tp>(_VSTD::forward<typename tuple_element<_Indx,
429                                       typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<_Indx>(__t)))...
430            {}
431
432    template <class _Alloc, class _Tuple,
433              class = typename enable_if
434                      <
435                         __tuple_constructible<_Tuple, tuple<_Tp...> >::value
436                      >::type
437             >
438        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
439        __tuple_impl(allocator_arg_t, const _Alloc& __a, _Tuple&& __t)
440            : __tuple_leaf<_Indx, _Tp>(__uses_alloc_ctor<_Tp, _Alloc, typename tuple_element<_Indx,
441                                       typename __make_tuple_types<_Tuple>::type>::type>(), __a,
442                                       _VSTD::forward<typename tuple_element<_Indx,
443                                       typename __make_tuple_types<_Tuple>::type>::type>(_VSTD::get<_Indx>(__t)))...
444            {}
445
446    __tuple_impl(const __tuple_impl&) = default;
447    __tuple_impl(__tuple_impl&&) = default;
448
449    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
450    void swap(__tuple_impl& __t)
451        _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
452    {
453        _VSTD::__swallow(__tuple_leaf<_Indx, _Tp>::swap(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t))...);
454    }
455};
456
457template<class _Dest, class _Source, size_t ..._Np>
458_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
459void __memberwise_copy_assign(_Dest& __dest, _Source const& __source, __tuple_indices<_Np...>) {
460    _VSTD::__swallow(((_VSTD::get<_Np>(__dest) = _VSTD::get<_Np>(__source)), void(), 0)...);
461}
462
463template<class _Dest, class _Source, class ..._Up, size_t ..._Np>
464_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
465void __memberwise_forward_assign(_Dest& __dest, _Source&& __source, __tuple_types<_Up...>, __tuple_indices<_Np...>) {
466    _VSTD::__swallow(((
467        _VSTD::get<_Np>(__dest) = _VSTD::forward<_Up>(_VSTD::get<_Np>(__source))
468    ), void(), 0)...);
469}
470
471template <class ..._Tp>
472class _LIBCPP_TEMPLATE_VIS tuple
473{
474    typedef __tuple_impl<typename __make_tuple_indices<sizeof...(_Tp)>::type, _Tp...> _BaseT;
475
476    _BaseT __base_;
477
478    template <size_t _Jp, class ..._Up> friend _LIBCPP_CONSTEXPR_AFTER_CXX11
479        typename tuple_element<_Jp, tuple<_Up...> >::type& get(tuple<_Up...>&) _NOEXCEPT;
480    template <size_t _Jp, class ..._Up> friend _LIBCPP_CONSTEXPR_AFTER_CXX11
481        const typename tuple_element<_Jp, tuple<_Up...> >::type& get(const tuple<_Up...>&) _NOEXCEPT;
482    template <size_t _Jp, class ..._Up> friend _LIBCPP_CONSTEXPR_AFTER_CXX11
483        typename tuple_element<_Jp, tuple<_Up...> >::type&& get(tuple<_Up...>&&) _NOEXCEPT;
484    template <size_t _Jp, class ..._Up> friend _LIBCPP_CONSTEXPR_AFTER_CXX11
485        const typename tuple_element<_Jp, tuple<_Up...> >::type&& get(const tuple<_Up...>&&) _NOEXCEPT;
486public:
487    // [tuple.cnstr]
488
489    // tuple() constructors (including allocator_arg_t variants)
490    template <template<class...> class _IsImpDefault = __is_implicitly_default_constructible, __enable_if_t<
491        _And<
492            _IsImpDefault<_Tp>... // explicit check
493        >::value
494    , int> = 0>
495    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
496    tuple()
497        _NOEXCEPT_(_And<is_nothrow_default_constructible<_Tp>...>::value)
498    { }
499
500    template <template<class...> class _IsImpDefault = __is_implicitly_default_constructible,
501              template<class...> class _IsDefault = is_default_constructible, __enable_if_t<
502        _And<
503            _IsDefault<_Tp>...,
504            _Not<_Lazy<_And, _IsImpDefault<_Tp>...> > // explicit check
505        >::value
506    , int> = 0>
507    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
508    explicit tuple()
509        _NOEXCEPT_(_And<is_nothrow_default_constructible<_Tp>...>::value)
510    { }
511
512    template <class _Alloc, template<class...> class _IsImpDefault = __is_implicitly_default_constructible, __enable_if_t<
513        _And<
514            _IsImpDefault<_Tp>... // explicit check
515        >::value
516    , int> = 0>
517    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
518    tuple(allocator_arg_t, _Alloc const& __a)
519      : __base_(allocator_arg_t(), __a,
520                    __tuple_indices<>(), __tuple_types<>(),
521                    typename __make_tuple_indices<sizeof...(_Tp), 0>::type(),
522                    __tuple_types<_Tp...>()) {}
523
524    template <class _Alloc,
525              template<class...> class _IsImpDefault = __is_implicitly_default_constructible,
526              template<class...> class _IsDefault = is_default_constructible, __enable_if_t<
527        _And<
528            _IsDefault<_Tp>...,
529            _Not<_Lazy<_And, _IsImpDefault<_Tp>...> > // explicit check
530        >::value
531    , int> = 0>
532    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
533    explicit tuple(allocator_arg_t, _Alloc const& __a)
534      : __base_(allocator_arg_t(), __a,
535                    __tuple_indices<>(), __tuple_types<>(),
536                    typename __make_tuple_indices<sizeof...(_Tp), 0>::type(),
537                    __tuple_types<_Tp...>()) {}
538
539    // tuple(const T&...) constructors (including allocator_arg_t variants)
540    template <template<class...> class _And = _And, __enable_if_t<
541        _And<
542            _BoolConstant<sizeof...(_Tp) >= 1>,
543            is_copy_constructible<_Tp>...,
544            is_convertible<const _Tp&, _Tp>... // explicit check
545        >::value
546    , int> = 0>
547    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
548    tuple(const _Tp& ... __t)
549        _NOEXCEPT_(_And<is_nothrow_copy_constructible<_Tp>...>::value)
550        : __base_(typename __make_tuple_indices<sizeof...(_Tp)>::type(),
551                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
552                typename __make_tuple_indices<0>::type(),
553                typename __make_tuple_types<tuple, 0>::type(),
554                __t...
555               ) {}
556
557    template <template<class...> class _And = _And, __enable_if_t<
558        _And<
559            _BoolConstant<sizeof...(_Tp) >= 1>,
560            is_copy_constructible<_Tp>...,
561            _Not<_Lazy<_And, is_convertible<const _Tp&, _Tp>...> > // explicit check
562        >::value
563    , int> = 0>
564    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
565    explicit tuple(const _Tp& ... __t)
566        _NOEXCEPT_(_And<is_nothrow_copy_constructible<_Tp>...>::value)
567        : __base_(typename __make_tuple_indices<sizeof...(_Tp)>::type(),
568                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
569                typename __make_tuple_indices<0>::type(),
570                typename __make_tuple_types<tuple, 0>::type(),
571                __t...
572               ) {}
573
574    template <class _Alloc, template<class...> class _And = _And, __enable_if_t<
575        _And<
576            _BoolConstant<sizeof...(_Tp) >= 1>,
577            is_copy_constructible<_Tp>...,
578            is_convertible<const _Tp&, _Tp>... // explicit check
579        >::value
580    , int> = 0>
581    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
582    tuple(allocator_arg_t, const _Alloc& __a, const _Tp& ... __t)
583        : __base_(allocator_arg_t(), __a,
584                typename __make_tuple_indices<sizeof...(_Tp)>::type(),
585                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
586                typename __make_tuple_indices<0>::type(),
587                typename __make_tuple_types<tuple, 0>::type(),
588                __t...
589               ) {}
590
591    template <class _Alloc, template<class...> class _And = _And, __enable_if_t<
592        _And<
593            _BoolConstant<sizeof...(_Tp) >= 1>,
594            is_copy_constructible<_Tp>...,
595            _Not<_Lazy<_And, is_convertible<const _Tp&, _Tp>...> > // explicit check
596        >::value
597    , int> = 0>
598    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
599    explicit tuple(allocator_arg_t, const _Alloc& __a, const _Tp& ... __t)
600        : __base_(allocator_arg_t(), __a,
601                typename __make_tuple_indices<sizeof...(_Tp)>::type(),
602                typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(),
603                typename __make_tuple_indices<0>::type(),
604                typename __make_tuple_types<tuple, 0>::type(),
605                __t...
606               ) {}
607
608    // tuple(U&& ...) constructors (including allocator_arg_t variants)
609    template <class ..._Up> struct _IsThisTuple : false_type { };
610    template <class _Up> struct _IsThisTuple<_Up> : is_same<__uncvref_t<_Up>, tuple> { };
611
612    template <class ..._Up>
613    struct _EnableUTypesCtor : _And<
614        _BoolConstant<sizeof...(_Tp) >= 1>,
615        _Not<_IsThisTuple<_Up...> >, // extension to allow mis-behaved user constructors
616        is_constructible<_Tp, _Up>...
617    > { };
618
619    template <class ..._Up, __enable_if_t<
620        _And<
621            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
622            _EnableUTypesCtor<_Up...>,
623            is_convertible<_Up, _Tp>... // explicit check
624        >::value
625    , int> = 0>
626    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
627    tuple(_Up&&... __u)
628        _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, _Up>...>::value))
629        : __base_(typename __make_tuple_indices<sizeof...(_Up)>::type(),
630                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
631                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
632                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
633                    _VSTD::forward<_Up>(__u)...) {}
634
635    template <class ..._Up, __enable_if_t<
636        _And<
637            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
638            _EnableUTypesCtor<_Up...>,
639            _Not<_Lazy<_And, is_convertible<_Up, _Tp>...> > // explicit check
640        >::value
641    , int> = 0>
642    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
643    explicit tuple(_Up&&... __u)
644        _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, _Up>...>::value))
645        : __base_(typename __make_tuple_indices<sizeof...(_Up)>::type(),
646                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
647                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
648                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
649                    _VSTD::forward<_Up>(__u)...) {}
650
651    template <class _Alloc, class ..._Up, __enable_if_t<
652        _And<
653            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
654            _EnableUTypesCtor<_Up...>,
655            is_convertible<_Up, _Tp>... // explicit check
656        >::value
657    , int> = 0>
658    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
659    tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u)
660        : __base_(allocator_arg_t(), __a,
661                    typename __make_tuple_indices<sizeof...(_Up)>::type(),
662                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
663                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
664                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
665                    _VSTD::forward<_Up>(__u)...) {}
666
667    template <class _Alloc, class ..._Up, __enable_if_t<
668        _And<
669            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
670            _EnableUTypesCtor<_Up...>,
671            _Not<_Lazy<_And, is_convertible<_Up, _Tp>...> > // explicit check
672        >::value
673    , int> = 0>
674    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
675    explicit tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u)
676        : __base_(allocator_arg_t(), __a,
677                    typename __make_tuple_indices<sizeof...(_Up)>::type(),
678                    typename __make_tuple_types<tuple, sizeof...(_Up)>::type(),
679                    typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(),
680                    typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(),
681                    _VSTD::forward<_Up>(__u)...) {}
682
683    // Copy and move constructors (including the allocator_arg_t variants)
684    tuple(const tuple&) = default;
685    tuple(tuple&&) = default;
686
687    template <class _Alloc, template<class...> class _And = _And, __enable_if_t<
688        _And<is_copy_constructible<_Tp>...>::value
689    , int> = 0>
690    tuple(allocator_arg_t, const _Alloc& __alloc, const tuple& __t)
691        : __base_(allocator_arg_t(), __alloc, __t)
692    { }
693
694    template <class _Alloc, template<class...> class _And = _And, __enable_if_t<
695        _And<is_move_constructible<_Tp>...>::value
696    , int> = 0>
697    tuple(allocator_arg_t, const _Alloc& __alloc, tuple&& __t)
698        : __base_(allocator_arg_t(), __alloc, _VSTD::move(__t))
699    { }
700
701    // tuple(const tuple<U...>&) constructors (including allocator_arg_t variants)
702    template <class ..._Up>
703    struct _EnableCopyFromOtherTuple : _And<
704        _Not<is_same<tuple<_Tp...>, tuple<_Up...> > >,
705        _Lazy<_Or,
706            _BoolConstant<sizeof...(_Tp) != 1>,
707            // _Tp and _Up are 1-element packs - the pack expansions look
708            // weird to avoid tripping up the type traits in degenerate cases
709            _Lazy<_And,
710                _Not<is_convertible<const tuple<_Up>&, _Tp> >...,
711                _Not<is_constructible<_Tp, const tuple<_Up>&> >...
712            >
713        >,
714        is_constructible<_Tp, const _Up&>...
715    > { };
716
717    template <class ..._Up, __enable_if_t<
718        _And<
719            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
720            _EnableCopyFromOtherTuple<_Up...>,
721            is_convertible<const _Up&, _Tp>... // explicit check
722        >::value
723    , int> = 0>
724    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
725    tuple(const tuple<_Up...>& __t)
726        _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, const _Up&>...>::value))
727        : __base_(__t)
728    { }
729
730    template <class ..._Up, __enable_if_t<
731        _And<
732            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
733            _EnableCopyFromOtherTuple<_Up...>,
734            _Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> > // explicit check
735        >::value
736    , int> = 0>
737    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
738    explicit tuple(const tuple<_Up...>& __t)
739        _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, const _Up&>...>::value))
740        : __base_(__t)
741    { }
742
743    template <class ..._Up, class _Alloc, __enable_if_t<
744        _And<
745            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
746            _EnableCopyFromOtherTuple<_Up...>,
747            is_convertible<const _Up&, _Tp>... // explicit check
748        >::value
749    , int> = 0>
750    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
751    tuple(allocator_arg_t, const _Alloc& __a, const tuple<_Up...>& __t)
752        : __base_(allocator_arg_t(), __a, __t)
753    { }
754
755    template <class ..._Up, class _Alloc, __enable_if_t<
756        _And<
757            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
758            _EnableCopyFromOtherTuple<_Up...>,
759            _Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> > // explicit check
760        >::value
761    , int> = 0>
762    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
763    explicit tuple(allocator_arg_t, const _Alloc& __a, const tuple<_Up...>& __t)
764        : __base_(allocator_arg_t(), __a, __t)
765    { }
766
767    // tuple(tuple<U...>&&) constructors (including allocator_arg_t variants)
768    template <class ..._Up>
769    struct _EnableMoveFromOtherTuple : _And<
770        _Not<is_same<tuple<_Tp...>, tuple<_Up...> > >,
771        _Lazy<_Or,
772            _BoolConstant<sizeof...(_Tp) != 1>,
773            // _Tp and _Up are 1-element packs - the pack expansions look
774            // weird to avoid tripping up the type traits in degenerate cases
775            _Lazy<_And,
776                _Not<is_convertible<tuple<_Up>, _Tp> >...,
777                _Not<is_constructible<_Tp, tuple<_Up> > >...
778            >
779        >,
780        is_constructible<_Tp, _Up>...
781    > { };
782
783    template <class ..._Up, __enable_if_t<
784        _And<
785            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
786            _EnableMoveFromOtherTuple<_Up...>,
787            is_convertible<_Up, _Tp>... // explicit check
788        >::value
789    , int> = 0>
790    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
791    tuple(tuple<_Up...>&& __t)
792        _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, _Up>...>::value))
793        : __base_(_VSTD::move(__t))
794    { }
795
796    template <class ..._Up, __enable_if_t<
797        _And<
798            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
799            _EnableMoveFromOtherTuple<_Up...>,
800            _Not<_Lazy<_And, is_convertible<_Up, _Tp>...> > // explicit check
801        >::value
802    , int> = 0>
803    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
804    explicit tuple(tuple<_Up...>&& __t)
805        _NOEXCEPT_((_And<is_nothrow_constructible<_Tp, _Up>...>::value))
806        : __base_(_VSTD::move(__t))
807    { }
808
809    template <class _Alloc, class ..._Up, __enable_if_t<
810        _And<
811            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
812            _EnableMoveFromOtherTuple<_Up...>,
813            is_convertible<_Up, _Tp>... // explicit check
814        >::value
815    , int> = 0>
816    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
817    tuple(allocator_arg_t, const _Alloc& __a, tuple<_Up...>&& __t)
818        : __base_(allocator_arg_t(), __a, _VSTD::move(__t))
819    { }
820
821    template <class _Alloc, class ..._Up, __enable_if_t<
822        _And<
823            _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>,
824            _EnableMoveFromOtherTuple<_Up...>,
825            _Not<_Lazy<_And, is_convertible<_Up, _Tp>...> > // explicit check
826        >::value
827    , int> = 0>
828    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
829    explicit tuple(allocator_arg_t, const _Alloc& __a, tuple<_Up...>&& __t)
830        : __base_(allocator_arg_t(), __a, _VSTD::move(__t))
831    { }
832
833    // tuple(const pair<U1, U2>&) constructors (including allocator_arg_t variants)
834    template <class _Up1, class _Up2, class ..._DependentTp>
835    struct _EnableImplicitCopyFromPair : _And<
836        is_constructible<_FirstType<_DependentTp...>, const _Up1&>,
837        is_constructible<_SecondType<_DependentTp...>, const _Up2&>,
838        is_convertible<const _Up1&, _FirstType<_DependentTp...> >, // explicit check
839        is_convertible<const _Up2&, _SecondType<_DependentTp...> >
840    > { };
841
842    template <class _Up1, class _Up2, class ..._DependentTp>
843    struct _EnableExplicitCopyFromPair : _And<
844        is_constructible<_FirstType<_DependentTp...>, const _Up1&>,
845        is_constructible<_SecondType<_DependentTp...>, const _Up2&>,
846        _Not<is_convertible<const _Up1&, _FirstType<_DependentTp...> > >, // explicit check
847        _Not<is_convertible<const _Up2&, _SecondType<_DependentTp...> > >
848    > { };
849
850    template <class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
851        _And<
852            _BoolConstant<sizeof...(_Tp) == 2>,
853            _EnableImplicitCopyFromPair<_Up1, _Up2, _Tp...>
854        >::value
855    , int> = 0>
856    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
857    tuple(const pair<_Up1, _Up2>& __p)
858        _NOEXCEPT_((_And<
859            is_nothrow_constructible<_FirstType<_Tp...>, const _Up1&>,
860            is_nothrow_constructible<_SecondType<_Tp...>, const _Up2&>
861        >::value))
862        : __base_(__p)
863    { }
864
865    template <class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
866        _And<
867            _BoolConstant<sizeof...(_Tp) == 2>,
868            _EnableExplicitCopyFromPair<_Up1, _Up2, _Tp...>
869        >::value
870    , int> = 0>
871    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
872    explicit tuple(const pair<_Up1, _Up2>& __p)
873        _NOEXCEPT_((_And<
874            is_nothrow_constructible<_FirstType<_Tp...>, const _Up1&>,
875            is_nothrow_constructible<_SecondType<_Tp...>, const _Up2&>
876        >::value))
877        : __base_(__p)
878    { }
879
880    template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
881        _And<
882            _BoolConstant<sizeof...(_Tp) == 2>,
883            _EnableImplicitCopyFromPair<_Up1, _Up2, _Tp...>
884        >::value
885    , int> = 0>
886    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
887    tuple(allocator_arg_t, const _Alloc& __a, const pair<_Up1, _Up2>& __p)
888        : __base_(allocator_arg_t(), __a, __p)
889    { }
890
891    template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
892        _And<
893            _BoolConstant<sizeof...(_Tp) == 2>,
894            _EnableExplicitCopyFromPair<_Up1, _Up2, _Tp...>
895        >::value
896    , int> = 0>
897    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
898    explicit tuple(allocator_arg_t, const _Alloc& __a, const pair<_Up1, _Up2>& __p)
899        : __base_(allocator_arg_t(), __a, __p)
900    { }
901
902    // tuple(pair<U1, U2>&&) constructors (including allocator_arg_t variants)
903    template <class _Up1, class _Up2, class ..._DependentTp>
904    struct _EnableImplicitMoveFromPair : _And<
905        is_constructible<_FirstType<_DependentTp...>, _Up1>,
906        is_constructible<_SecondType<_DependentTp...>, _Up2>,
907        is_convertible<_Up1, _FirstType<_DependentTp...> >, // explicit check
908        is_convertible<_Up2, _SecondType<_DependentTp...> >
909    > { };
910
911    template <class _Up1, class _Up2, class ..._DependentTp>
912    struct _EnableExplicitMoveFromPair : _And<
913        is_constructible<_FirstType<_DependentTp...>, _Up1>,
914        is_constructible<_SecondType<_DependentTp...>, _Up2>,
915        _Not<is_convertible<_Up1, _FirstType<_DependentTp...> > >, // explicit check
916        _Not<is_convertible<_Up2, _SecondType<_DependentTp...> > >
917    > { };
918
919    template <class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
920        _And<
921            _BoolConstant<sizeof...(_Tp) == 2>,
922            _EnableImplicitMoveFromPair<_Up1, _Up2, _Tp...>
923        >::value
924    , int> = 0>
925    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
926    tuple(pair<_Up1, _Up2>&& __p)
927        _NOEXCEPT_((_And<
928            is_nothrow_constructible<_FirstType<_Tp...>, _Up1>,
929            is_nothrow_constructible<_SecondType<_Tp...>, _Up2>
930        >::value))
931        : __base_(_VSTD::move(__p))
932    { }
933
934    template <class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
935        _And<
936            _BoolConstant<sizeof...(_Tp) == 2>,
937            _EnableExplicitMoveFromPair<_Up1, _Up2, _Tp...>
938        >::value
939    , int> = 0>
940    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
941    explicit tuple(pair<_Up1, _Up2>&& __p)
942        _NOEXCEPT_((_And<
943            is_nothrow_constructible<_FirstType<_Tp...>, _Up1>,
944            is_nothrow_constructible<_SecondType<_Tp...>, _Up2>
945        >::value))
946        : __base_(_VSTD::move(__p))
947    { }
948
949    template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
950        _And<
951            _BoolConstant<sizeof...(_Tp) == 2>,
952            _EnableImplicitMoveFromPair<_Up1, _Up2, _Tp...>
953        >::value
954    , int> = 0>
955    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
956    tuple(allocator_arg_t, const _Alloc& __a, pair<_Up1, _Up2>&& __p)
957        : __base_(allocator_arg_t(), __a, _VSTD::move(__p))
958    { }
959
960    template <class _Alloc, class _Up1, class _Up2, template<class...> class _And = _And, __enable_if_t<
961        _And<
962            _BoolConstant<sizeof...(_Tp) == 2>,
963            _EnableExplicitMoveFromPair<_Up1, _Up2, _Tp...>
964        >::value
965    , int> = 0>
966    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
967    explicit tuple(allocator_arg_t, const _Alloc& __a, pair<_Up1, _Up2>&& __p)
968        : __base_(allocator_arg_t(), __a, _VSTD::move(__p))
969    { }
970
971    // [tuple.assign]
972    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
973    tuple& operator=(_If<_And<is_copy_assignable<_Tp>...>::value, tuple, __nat> const& __tuple)
974        _NOEXCEPT_((_And<is_nothrow_copy_assignable<_Tp>...>::value))
975    {
976        _VSTD::__memberwise_copy_assign(*this, __tuple,
977            typename __make_tuple_indices<sizeof...(_Tp)>::type());
978        return *this;
979    }
980
981    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
982    tuple& operator=(_If<_And<is_move_assignable<_Tp>...>::value, tuple, __nat>&& __tuple)
983        _NOEXCEPT_((_And<is_nothrow_move_assignable<_Tp>...>::value))
984    {
985        _VSTD::__memberwise_forward_assign(*this, _VSTD::move(__tuple),
986            __tuple_types<_Tp...>(),
987            typename __make_tuple_indices<sizeof...(_Tp)>::type());
988        return *this;
989    }
990
991    template<class... _Up, __enable_if_t<
992        _And<
993            _BoolConstant<sizeof...(_Tp) == sizeof...(_Up)>,
994            is_assignable<_Tp&, _Up const&>...
995        >::value
996    ,int> = 0>
997    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
998    tuple& operator=(tuple<_Up...> const& __tuple)
999        _NOEXCEPT_((_And<is_nothrow_assignable<_Tp&, _Up const&>...>::value))
1000    {
1001        _VSTD::__memberwise_copy_assign(*this, __tuple,
1002            typename __make_tuple_indices<sizeof...(_Tp)>::type());
1003        return *this;
1004    }
1005
1006    template<class... _Up, __enable_if_t<
1007        _And<
1008            _BoolConstant<sizeof...(_Tp) == sizeof...(_Up)>,
1009            is_assignable<_Tp&, _Up>...
1010        >::value
1011    ,int> = 0>
1012    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1013    tuple& operator=(tuple<_Up...>&& __tuple)
1014        _NOEXCEPT_((_And<is_nothrow_assignable<_Tp&, _Up>...>::value))
1015    {
1016        _VSTD::__memberwise_forward_assign(*this, _VSTD::move(__tuple),
1017            __tuple_types<_Up...>(),
1018            typename __make_tuple_indices<sizeof...(_Tp)>::type());
1019        return *this;
1020    }
1021
1022    template<class _Up1, class _Up2, class _Dep = true_type, __enable_if_t<
1023        _And<_Dep,
1024            _BoolConstant<sizeof...(_Tp) == 2>,
1025            is_assignable<_FirstType<_Tp..., _Dep>&, _Up1 const&>,
1026            is_assignable<_SecondType<_Tp..., _Dep>&, _Up2 const&>
1027        >::value
1028    ,int> = 0>
1029    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1030    tuple& operator=(pair<_Up1, _Up2> const& __pair)
1031        _NOEXCEPT_((_And<
1032            is_nothrow_assignable<_FirstType<_Tp...>&, _Up1 const&>,
1033            is_nothrow_assignable<_SecondType<_Tp...>&, _Up2 const&>
1034        >::value))
1035    {
1036        _VSTD::get<0>(*this) = __pair.first;
1037        _VSTD::get<1>(*this) = __pair.second;
1038        return *this;
1039    }
1040
1041    template<class _Up1, class _Up2, class _Dep = true_type, __enable_if_t<
1042        _And<_Dep,
1043            _BoolConstant<sizeof...(_Tp) == 2>,
1044            is_assignable<_FirstType<_Tp..., _Dep>&, _Up1>,
1045            is_assignable<_SecondType<_Tp..., _Dep>&, _Up2>
1046        >::value
1047    ,int> = 0>
1048    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1049    tuple& operator=(pair<_Up1, _Up2>&& __pair)
1050        _NOEXCEPT_((_And<
1051            is_nothrow_assignable<_FirstType<_Tp...>&, _Up1>,
1052            is_nothrow_assignable<_SecondType<_Tp...>&, _Up2>
1053        >::value))
1054    {
1055        _VSTD::get<0>(*this) = _VSTD::forward<_Up1>(__pair.first);
1056        _VSTD::get<1>(*this) = _VSTD::forward<_Up2>(__pair.second);
1057        return *this;
1058    }
1059
1060    // EXTENSION
1061    template<class _Up, size_t _Np, class = __enable_if_t<
1062        _And<
1063            _BoolConstant<_Np == sizeof...(_Tp)>,
1064            is_assignable<_Tp&, _Up const&>...
1065        >::value
1066    > >
1067    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1068    tuple& operator=(array<_Up, _Np> const& __array)
1069        _NOEXCEPT_((_And<is_nothrow_assignable<_Tp&, _Up const&>...>::value))
1070    {
1071        _VSTD::__memberwise_copy_assign(*this, __array,
1072            typename __make_tuple_indices<sizeof...(_Tp)>::type());
1073        return *this;
1074    }
1075
1076    // EXTENSION
1077    template<class _Up, size_t _Np, class = void, class = __enable_if_t<
1078        _And<
1079            _BoolConstant<_Np == sizeof...(_Tp)>,
1080            is_assignable<_Tp&, _Up>...
1081        >::value
1082    > >
1083    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1084    tuple& operator=(array<_Up, _Np>&& __array)
1085        _NOEXCEPT_((_And<is_nothrow_assignable<_Tp&, _Up>...>::value))
1086    {
1087        _VSTD::__memberwise_forward_assign(*this, _VSTD::move(__array),
1088            __tuple_types<_If<true, _Up, _Tp>...>(),
1089            typename __make_tuple_indices<sizeof...(_Tp)>::type());
1090        return *this;
1091    }
1092
1093    // [tuple.swap]
1094    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1095    void swap(tuple& __t) _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
1096        {__base_.swap(__t.__base_);}
1097};
1098
1099template <>
1100class _LIBCPP_TEMPLATE_VIS tuple<>
1101{
1102public:
1103    _LIBCPP_INLINE_VISIBILITY constexpr
1104        tuple() _NOEXCEPT = default;
1105    template <class _Alloc>
1106    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1107        tuple(allocator_arg_t, const _Alloc&) _NOEXCEPT {}
1108    template <class _Alloc>
1109    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1110        tuple(allocator_arg_t, const _Alloc&, const tuple&) _NOEXCEPT {}
1111    template <class _Up>
1112    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1113        tuple(array<_Up, 0>) _NOEXCEPT {}
1114    template <class _Alloc, class _Up>
1115    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1116        tuple(allocator_arg_t, const _Alloc&, array<_Up, 0>) _NOEXCEPT {}
1117    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1118    void swap(tuple&) _NOEXCEPT {}
1119};
1120
1121#if _LIBCPP_STD_VER > 20
1122template <class... _TTypes, class... _UTypes, template<class> class _TQual, template<class> class _UQual>
1123    requires requires { typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; }
1124struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual> {
1125    using type = tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>;
1126};
1127
1128template <class... _TTypes, class... _UTypes>
1129    requires requires { typename tuple<common_type_t<_TTypes, _UTypes>...>; }
1130struct common_type<tuple<_TTypes...>, tuple<_UTypes...>> {
1131    using type = tuple<common_type_t<_TTypes, _UTypes>...>;
1132};
1133#endif // _LIBCPP_STD_VER > 20
1134
1135#if _LIBCPP_STD_VER > 14
1136template <class ..._Tp>
1137tuple(_Tp...) -> tuple<_Tp...>;
1138template <class _Tp1, class _Tp2>
1139tuple(pair<_Tp1, _Tp2>) -> tuple<_Tp1, _Tp2>;
1140template <class _Alloc, class ..._Tp>
1141tuple(allocator_arg_t, _Alloc, _Tp...) -> tuple<_Tp...>;
1142template <class _Alloc, class _Tp1, class _Tp2>
1143tuple(allocator_arg_t, _Alloc, pair<_Tp1, _Tp2>) -> tuple<_Tp1, _Tp2>;
1144template <class _Alloc, class ..._Tp>
1145tuple(allocator_arg_t, _Alloc, tuple<_Tp...>) -> tuple<_Tp...>;
1146#endif
1147
1148template <class ..._Tp>
1149inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1150typename enable_if
1151<
1152    __all<__is_swappable<_Tp>::value...>::value,
1153    void
1154>::type
1155swap(tuple<_Tp...>& __t, tuple<_Tp...>& __u)
1156                 _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value)
1157    {__t.swap(__u);}
1158
1159// get
1160
1161template <size_t _Ip, class ..._Tp>
1162inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1163typename tuple_element<_Ip, tuple<_Tp...> >::type&
1164get(tuple<_Tp...>& __t) _NOEXCEPT
1165{
1166    typedef _LIBCPP_NODEBUG typename tuple_element<_Ip, tuple<_Tp...> >::type type;
1167    return static_cast<__tuple_leaf<_Ip, type>&>(__t.__base_).get();
1168}
1169
1170template <size_t _Ip, class ..._Tp>
1171inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1172const typename tuple_element<_Ip, tuple<_Tp...> >::type&
1173get(const tuple<_Tp...>& __t) _NOEXCEPT
1174{
1175    typedef _LIBCPP_NODEBUG typename tuple_element<_Ip, tuple<_Tp...> >::type type;
1176    return static_cast<const __tuple_leaf<_Ip, type>&>(__t.__base_).get();
1177}
1178
1179template <size_t _Ip, class ..._Tp>
1180inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1181typename tuple_element<_Ip, tuple<_Tp...> >::type&&
1182get(tuple<_Tp...>&& __t) _NOEXCEPT
1183{
1184    typedef _LIBCPP_NODEBUG typename tuple_element<_Ip, tuple<_Tp...> >::type type;
1185    return static_cast<type&&>(
1186             static_cast<__tuple_leaf<_Ip, type>&&>(__t.__base_).get());
1187}
1188
1189template <size_t _Ip, class ..._Tp>
1190inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1191const typename tuple_element<_Ip, tuple<_Tp...> >::type&&
1192get(const tuple<_Tp...>&& __t) _NOEXCEPT
1193{
1194    typedef _LIBCPP_NODEBUG typename tuple_element<_Ip, tuple<_Tp...> >::type type;
1195    return static_cast<const type&&>(
1196             static_cast<const __tuple_leaf<_Ip, type>&&>(__t.__base_).get());
1197}
1198
1199#if _LIBCPP_STD_VER > 11
1200
1201namespace __find_detail {
1202
1203static constexpr size_t __not_found = static_cast<size_t>(-1);
1204static constexpr size_t __ambiguous = __not_found - 1;
1205
1206inline _LIBCPP_INLINE_VISIBILITY
1207constexpr size_t __find_idx_return(size_t __curr_i, size_t __res, bool __matches) {
1208    return !__matches ? __res :
1209        (__res == __not_found ? __curr_i : __ambiguous);
1210}
1211
1212template <size_t _Nx>
1213inline _LIBCPP_INLINE_VISIBILITY
1214constexpr size_t __find_idx(size_t __i, const bool (&__matches)[_Nx]) {
1215  return __i == _Nx ? __not_found :
1216      __find_idx_return(__i, __find_idx(__i + 1, __matches), __matches[__i]);
1217}
1218
1219template <class _T1, class ..._Args>
1220struct __find_exactly_one_checked {
1221    static constexpr bool __matches[sizeof...(_Args)] = {is_same<_T1, _Args>::value...};
1222    static constexpr size_t value = __find_detail::__find_idx(0, __matches);
1223    static_assert(value != __not_found, "type not found in type list" );
1224    static_assert(value != __ambiguous, "type occurs more than once in type list");
1225};
1226
1227template <class _T1>
1228struct __find_exactly_one_checked<_T1> {
1229    static_assert(!is_same<_T1, _T1>::value, "type not in empty type list");
1230};
1231
1232} // namespace __find_detail
1233
1234template <typename _T1, typename... _Args>
1235struct __find_exactly_one_t
1236    : public __find_detail::__find_exactly_one_checked<_T1, _Args...> {
1237};
1238
1239template <class _T1, class... _Args>
1240inline _LIBCPP_INLINE_VISIBILITY
1241constexpr _T1& get(tuple<_Args...>& __tup) noexcept
1242{
1243    return _VSTD::get<__find_exactly_one_t<_T1, _Args...>::value>(__tup);
1244}
1245
1246template <class _T1, class... _Args>
1247inline _LIBCPP_INLINE_VISIBILITY
1248constexpr _T1 const& get(tuple<_Args...> const& __tup) noexcept
1249{
1250    return _VSTD::get<__find_exactly_one_t<_T1, _Args...>::value>(__tup);
1251}
1252
1253template <class _T1, class... _Args>
1254inline _LIBCPP_INLINE_VISIBILITY
1255constexpr _T1&& get(tuple<_Args...>&& __tup) noexcept
1256{
1257    return _VSTD::get<__find_exactly_one_t<_T1, _Args...>::value>(_VSTD::move(__tup));
1258}
1259
1260template <class _T1, class... _Args>
1261inline _LIBCPP_INLINE_VISIBILITY
1262constexpr _T1 const&& get(tuple<_Args...> const&& __tup) noexcept
1263{
1264    return _VSTD::get<__find_exactly_one_t<_T1, _Args...>::value>(_VSTD::move(__tup));
1265}
1266
1267#endif
1268
1269// tie
1270
1271template <class ..._Tp>
1272inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1273tuple<_Tp&...>
1274tie(_Tp&... __t) _NOEXCEPT
1275{
1276    return tuple<_Tp&...>(__t...);
1277}
1278
1279template <class _Up>
1280struct __ignore_t
1281{
1282    template <class _Tp>
1283    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1284    const __ignore_t& operator=(_Tp&&) const {return *this;}
1285};
1286
1287namespace {
1288  constexpr __ignore_t<unsigned char> ignore = __ignore_t<unsigned char>();
1289} // namespace
1290
1291template <class... _Tp>
1292inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1293tuple<typename __unwrap_ref_decay<_Tp>::type...>
1294make_tuple(_Tp&&... __t)
1295{
1296    return tuple<typename __unwrap_ref_decay<_Tp>::type...>(_VSTD::forward<_Tp>(__t)...);
1297}
1298
1299template <class... _Tp>
1300inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1301tuple<_Tp&&...>
1302forward_as_tuple(_Tp&&... __t) _NOEXCEPT
1303{
1304    return tuple<_Tp&&...>(_VSTD::forward<_Tp>(__t)...);
1305}
1306
1307template <size_t _Ip>
1308struct __tuple_equal
1309{
1310    template <class _Tp, class _Up>
1311    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1312    bool operator()(const _Tp& __x, const _Up& __y)
1313    {
1314        return __tuple_equal<_Ip - 1>()(__x, __y) && _VSTD::get<_Ip-1>(__x) == _VSTD::get<_Ip-1>(__y);
1315    }
1316};
1317
1318template <>
1319struct __tuple_equal<0>
1320{
1321    template <class _Tp, class _Up>
1322    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1323    bool operator()(const _Tp&, const _Up&)
1324    {
1325        return true;
1326    }
1327};
1328
1329template <class ..._Tp, class ..._Up>
1330inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1331bool
1332operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
1333{
1334    static_assert (sizeof...(_Tp) == sizeof...(_Up), "Can't compare tuples of different sizes");
1335    return __tuple_equal<sizeof...(_Tp)>()(__x, __y);
1336}
1337
1338#if _LIBCPP_STD_VER > 17
1339
1340// operator<=>
1341
1342template <class ..._Tp, class ..._Up, size_t ..._Is>
1343_LIBCPP_HIDE_FROM_ABI constexpr
1344auto
1345__tuple_compare_three_way(const tuple<_Tp...>& __x, const tuple<_Up...>& __y, index_sequence<_Is...>) {
1346    common_comparison_category_t<__synth_three_way_result<_Tp, _Up>...> __result = strong_ordering::equal;
1347    static_cast<void>(((__result = _VSTD::__synth_three_way(_VSTD::get<_Is>(__x), _VSTD::get<_Is>(__y)), __result != 0) || ...));
1348    return __result;
1349}
1350
1351template <class ..._Tp, class ..._Up>
1352requires (sizeof...(_Tp) == sizeof...(_Up))
1353_LIBCPP_HIDE_FROM_ABI constexpr
1354common_comparison_category_t<__synth_three_way_result<_Tp, _Up>...>
1355operator<=>(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
1356{
1357    return _VSTD::__tuple_compare_three_way(__x, __y, index_sequence_for<_Tp...>{});
1358}
1359
1360#else // _LIBCPP_STD_VER > 17
1361
1362template <class ..._Tp, class ..._Up>
1363inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1364bool
1365operator!=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
1366{
1367    return !(__x == __y);
1368}
1369
1370template <size_t _Ip>
1371struct __tuple_less
1372{
1373    template <class _Tp, class _Up>
1374    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1375    bool operator()(const _Tp& __x, const _Up& __y)
1376    {
1377        const size_t __idx = tuple_size<_Tp>::value - _Ip;
1378        if (_VSTD::get<__idx>(__x) < _VSTD::get<__idx>(__y))
1379            return true;
1380        if (_VSTD::get<__idx>(__y) < _VSTD::get<__idx>(__x))
1381            return false;
1382        return __tuple_less<_Ip-1>()(__x, __y);
1383    }
1384};
1385
1386template <>
1387struct __tuple_less<0>
1388{
1389    template <class _Tp, class _Up>
1390    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1391    bool operator()(const _Tp&, const _Up&)
1392    {
1393        return false;
1394    }
1395};
1396
1397template <class ..._Tp, class ..._Up>
1398inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1399bool
1400operator<(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
1401{
1402    static_assert (sizeof...(_Tp) == sizeof...(_Up), "Can't compare tuples of different sizes");
1403    return __tuple_less<sizeof...(_Tp)>()(__x, __y);
1404}
1405
1406template <class ..._Tp, class ..._Up>
1407inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1408bool
1409operator>(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
1410{
1411    return __y < __x;
1412}
1413
1414template <class ..._Tp, class ..._Up>
1415inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1416bool
1417operator>=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
1418{
1419    return !(__x < __y);
1420}
1421
1422template <class ..._Tp, class ..._Up>
1423inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1424bool
1425operator<=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y)
1426{
1427    return !(__y < __x);
1428}
1429
1430#endif // _LIBCPP_STD_VER > 17
1431
1432// tuple_cat
1433
1434template <class _Tp, class _Up> struct __tuple_cat_type;
1435
1436template <class ..._Ttypes, class ..._Utypes>
1437struct __tuple_cat_type<tuple<_Ttypes...>, __tuple_types<_Utypes...> >
1438{
1439    typedef _LIBCPP_NODEBUG tuple<_Ttypes..., _Utypes...> type;
1440};
1441
1442template <class _ResultTuple, bool _Is_Tuple0TupleLike, class ..._Tuples>
1443struct __tuple_cat_return_1
1444{
1445};
1446
1447template <class ..._Types, class _Tuple0>
1448struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0>
1449{
1450  using type _LIBCPP_NODEBUG = typename __tuple_cat_type<
1451      tuple<_Types...>,
1452      typename __make_tuple_types<__uncvref_t<_Tuple0> >::type
1453    >::type;
1454};
1455
1456template <class ..._Types, class _Tuple0, class _Tuple1, class ..._Tuples>
1457struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0, _Tuple1, _Tuples...>
1458    : public __tuple_cat_return_1<
1459                 typename __tuple_cat_type<
1460                     tuple<_Types...>,
1461                     typename __make_tuple_types<__uncvref_t<_Tuple0> >::type
1462                 >::type,
1463                 __tuple_like<typename remove_reference<_Tuple1>::type>::value,
1464                 _Tuple1, _Tuples...>
1465{
1466};
1467
1468template <class ..._Tuples> struct __tuple_cat_return;
1469
1470template <class _Tuple0, class ..._Tuples>
1471struct __tuple_cat_return<_Tuple0, _Tuples...>
1472    : public __tuple_cat_return_1<tuple<>,
1473         __tuple_like<typename remove_reference<_Tuple0>::type>::value, _Tuple0,
1474                                                                     _Tuples...>
1475{
1476};
1477
1478template <>
1479struct __tuple_cat_return<>
1480{
1481    typedef _LIBCPP_NODEBUG tuple<> type;
1482};
1483
1484inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1485tuple<>
1486tuple_cat()
1487{
1488    return tuple<>();
1489}
1490
1491template <class _Rp, class _Indices, class _Tuple0, class ..._Tuples>
1492struct __tuple_cat_return_ref_imp;
1493
1494template <class ..._Types, size_t ..._I0, class _Tuple0>
1495struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>, _Tuple0>
1496{
1497    typedef _LIBCPP_NODEBUG typename remove_reference<_Tuple0>::type _T0;
1498    typedef tuple<_Types..., typename __apply_cv<_Tuple0,
1499                          typename tuple_element<_I0, _T0>::type>::type&&...> type;
1500};
1501
1502template <class ..._Types, size_t ..._I0, class _Tuple0, class _Tuple1, class ..._Tuples>
1503struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>,
1504                                  _Tuple0, _Tuple1, _Tuples...>
1505    : public __tuple_cat_return_ref_imp<
1506         tuple<_Types..., typename __apply_cv<_Tuple0,
1507               typename tuple_element<_I0,
1508                  typename remove_reference<_Tuple0>::type>::type>::type&&...>,
1509         typename __make_tuple_indices<tuple_size<typename
1510                                 remove_reference<_Tuple1>::type>::value>::type,
1511         _Tuple1, _Tuples...>
1512{
1513};
1514
1515template <class _Tuple0, class ..._Tuples>
1516struct __tuple_cat_return_ref
1517    : public __tuple_cat_return_ref_imp<tuple<>,
1518               typename __make_tuple_indices<
1519                        tuple_size<typename remove_reference<_Tuple0>::type>::value
1520               >::type, _Tuple0, _Tuples...>
1521{
1522};
1523
1524template <class _Types, class _I0, class _J0>
1525struct __tuple_cat;
1526
1527template <class ..._Types, size_t ..._I0, size_t ..._J0>
1528struct __tuple_cat<tuple<_Types...>, __tuple_indices<_I0...>, __tuple_indices<_J0...> >
1529{
1530    template <class _Tuple0>
1531    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1532    typename __tuple_cat_return_ref<tuple<_Types...>&&, _Tuple0&&>::type
1533    operator()(tuple<_Types...> __t, _Tuple0&& __t0)
1534    {
1535        (void)__t; // avoid unused parameter warning on GCC when _I0 is empty
1536        return _VSTD::forward_as_tuple(
1537            _VSTD::forward<_Types>(_VSTD::get<_I0>(__t))...,
1538            _VSTD::get<_J0>(_VSTD::forward<_Tuple0>(__t0))...);
1539    }
1540
1541    template <class _Tuple0, class _Tuple1, class ..._Tuples>
1542    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1543    typename __tuple_cat_return_ref<tuple<_Types...>&&, _Tuple0&&, _Tuple1&&, _Tuples&&...>::type
1544    operator()(tuple<_Types...> __t, _Tuple0&& __t0, _Tuple1&& __t1, _Tuples&& ...__tpls)
1545    {
1546        (void)__t; // avoid unused parameter warning on GCC when _I0 is empty
1547        typedef _LIBCPP_NODEBUG typename remove_reference<_Tuple0>::type _T0;
1548        typedef _LIBCPP_NODEBUG typename remove_reference<_Tuple1>::type _T1;
1549        return __tuple_cat<
1550            tuple<_Types...,
1551                  typename __apply_cv<_Tuple0, typename tuple_element<
1552                                                   _J0, _T0>::type>::type&&...>,
1553            typename __make_tuple_indices<sizeof...(_Types) +
1554                                          tuple_size<_T0>::value>::type,
1555            typename __make_tuple_indices<tuple_size<_T1>::value>::type>()(
1556            _VSTD::forward_as_tuple(
1557                _VSTD::forward<_Types>(_VSTD::get<_I0>(__t))...,
1558                _VSTD::get<_J0>(_VSTD::forward<_Tuple0>(__t0))...),
1559            _VSTD::forward<_Tuple1>(__t1), _VSTD::forward<_Tuples>(__tpls)...);
1560    }
1561};
1562
1563template <class _Tuple0, class... _Tuples>
1564inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
1565typename __tuple_cat_return<_Tuple0, _Tuples...>::type
1566tuple_cat(_Tuple0&& __t0, _Tuples&&... __tpls)
1567{
1568    typedef _LIBCPP_NODEBUG typename remove_reference<_Tuple0>::type _T0;
1569    return __tuple_cat<tuple<>, __tuple_indices<>,
1570                  typename __make_tuple_indices<tuple_size<_T0>::value>::type>()
1571                  (tuple<>(), _VSTD::forward<_Tuple0>(__t0),
1572                                            _VSTD::forward<_Tuples>(__tpls)...);
1573}
1574
1575template <class ..._Tp, class _Alloc>
1576struct _LIBCPP_TEMPLATE_VIS uses_allocator<tuple<_Tp...>, _Alloc>
1577    : true_type {};
1578
1579template <class _T1, class _T2>
1580template <class... _Args1, class... _Args2, size_t ..._I1, size_t ..._I2>
1581inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1582pair<_T1, _T2>::pair(piecewise_construct_t,
1583                     tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
1584                     __tuple_indices<_I1...>, __tuple_indices<_I2...>)
1585    :  first(_VSTD::forward<_Args1>(_VSTD::get<_I1>( __first_args))...),
1586      second(_VSTD::forward<_Args2>(_VSTD::get<_I2>(__second_args))...)
1587{
1588}
1589
1590#if _LIBCPP_STD_VER > 14
1591template <class _Tp>
1592inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value;
1593
1594#define _LIBCPP_NOEXCEPT_RETURN(...) noexcept(noexcept(__VA_ARGS__)) { return __VA_ARGS__; }
1595
1596template <class _Fn, class _Tuple, size_t ..._Id>
1597inline _LIBCPP_INLINE_VISIBILITY
1598constexpr decltype(auto) __apply_tuple_impl(_Fn && __f, _Tuple && __t,
1599                                            __tuple_indices<_Id...>)
1600_LIBCPP_NOEXCEPT_RETURN(
1601    _VSTD::__invoke(
1602        _VSTD::forward<_Fn>(__f),
1603        _VSTD::get<_Id>(_VSTD::forward<_Tuple>(__t))...)
1604)
1605
1606template <class _Fn, class _Tuple>
1607inline _LIBCPP_INLINE_VISIBILITY
1608constexpr decltype(auto) apply(_Fn && __f, _Tuple && __t)
1609_LIBCPP_NOEXCEPT_RETURN(
1610    _VSTD::__apply_tuple_impl(
1611        _VSTD::forward<_Fn>(__f), _VSTD::forward<_Tuple>(__t),
1612        typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{})
1613)
1614
1615template <class _Tp, class _Tuple, size_t... _Idx>
1616inline _LIBCPP_INLINE_VISIBILITY
1617constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>)
1618_LIBCPP_NOEXCEPT_RETURN(
1619    _Tp(_VSTD::get<_Idx>(_VSTD::forward<_Tuple>(__t))...)
1620)
1621
1622template <class _Tp, class _Tuple>
1623inline _LIBCPP_INLINE_VISIBILITY
1624constexpr _Tp make_from_tuple(_Tuple&& __t)
1625_LIBCPP_NOEXCEPT_RETURN(
1626    _VSTD::__make_from_tuple_impl<_Tp>(_VSTD::forward<_Tuple>(__t),
1627        typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{})
1628)
1629
1630#undef _LIBCPP_NOEXCEPT_RETURN
1631
1632#endif // _LIBCPP_STD_VER > 14
1633
1634#endif // !defined(_LIBCPP_CXX03_LANG)
1635
1636_LIBCPP_END_NAMESPACE_STD
1637
1638#endif // _LIBCPP_TUPLE
1639