xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/std/tuple (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
14fee23f9Smrg// <tuple> -*- C++ -*-
24fee23f9Smrg
3b1e83836Smrg// Copyright (C) 2007-2022 Free Software Foundation, Inc.
44fee23f9Smrg//
54fee23f9Smrg// This file is part of the GNU ISO C++ Library.  This library is free
64fee23f9Smrg// software; you can redistribute it and/or modify it under the
74fee23f9Smrg// terms of the GNU General Public License as published by the
84fee23f9Smrg// Free Software Foundation; either version 3, or (at your option)
94fee23f9Smrg// any later version.
104fee23f9Smrg
114fee23f9Smrg// This library is distributed in the hope that it will be useful,
124fee23f9Smrg// but WITHOUT ANY WARRANTY; without even the implied warranty of
134fee23f9Smrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
144fee23f9Smrg// GNU General Public License for more details.
154fee23f9Smrg
164fee23f9Smrg// Under Section 7 of GPL version 3, you are granted additional
174fee23f9Smrg// permissions described in the GCC Runtime Library Exception, version
184fee23f9Smrg// 3.1, as published by the Free Software Foundation.
194fee23f9Smrg
204fee23f9Smrg// You should have received a copy of the GNU General Public License and
214fee23f9Smrg// a copy of the GCC Runtime Library Exception along with this program;
224fee23f9Smrg// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
234fee23f9Smrg// <http://www.gnu.org/licenses/>.
244fee23f9Smrg
254fee23f9Smrg/** @file include/tuple
264fee23f9Smrg *  This is a Standard C++ Library header.
274fee23f9Smrg */
284fee23f9Smrg
294fee23f9Smrg#ifndef _GLIBCXX_TUPLE
304fee23f9Smrg#define _GLIBCXX_TUPLE 1
314fee23f9Smrg
324fee23f9Smrg#pragma GCC system_header
334fee23f9Smrg
3448fb7bfaSmrg#if __cplusplus < 201103L
354fee23f9Smrg# include <bits/c++0x_warning.h>
364fee23f9Smrg#else
374fee23f9Smrg
38b1e83836Smrg#include <bits/stl_pair.h>		// for std::pair
39b1e83836Smrg#include <bits/uses_allocator.h>	// for std::allocator_arg_t
40b1e83836Smrg#include <bits/utility.h>		// for std::get, std::tuple_size etc.
41b1e83836Smrg#include <bits/invoke.h>		// for std::__invoke
42fb8a8121Smrg#if __cplusplus > 201703L
43fb8a8121Smrg# include <compare>
44fb8a8121Smrg# define __cpp_lib_constexpr_tuple 201811L
45fb8a8121Smrg#endif
464fee23f9Smrg
4748fb7bfaSmrgnamespace std _GLIBCXX_VISIBILITY(default)
484fee23f9Smrg{
4948fb7bfaSmrg_GLIBCXX_BEGIN_NAMESPACE_VERSION
5048fb7bfaSmrg
5148fb7bfaSmrg  /**
5248fb7bfaSmrg   *  @addtogroup utilities
5348fb7bfaSmrg   *  @{
5448fb7bfaSmrg   */
5548fb7bfaSmrg
56b17d1066Smrg  template<typename... _Elements>
57b17d1066Smrg    class tuple;
58b17d1066Smrg
59b17d1066Smrg  template<typename _Tp>
60b17d1066Smrg    struct __is_empty_non_tuple : is_empty<_Tp> { };
61b17d1066Smrg
62b17d1066Smrg  // Using EBO for elements that are tuples causes ambiguous base errors.
63b17d1066Smrg  template<typename _El0, typename... _El>
64b17d1066Smrg    struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
65b17d1066Smrg
66b17d1066Smrg  // Use the Empty Base-class Optimization for empty, non-final types.
67b17d1066Smrg  template<typename _Tp>
68b17d1066Smrg    using __empty_not_final
69b1e83836Smrg    = __conditional_t<__is_final(_Tp), false_type,
70b1e83836Smrg		      __is_empty_non_tuple<_Tp>>;
71b17d1066Smrg
72b1e83836Smrg  template<size_t _Idx, typename _Head,
73b17d1066Smrg	   bool = __empty_not_final<_Head>::value>
744fee23f9Smrg    struct _Head_base;
754fee23f9Smrg
76b1e83836Smrg#if __has_cpp_attribute(__no_unique_address__)
77b1e83836Smrg  template<size_t _Idx, typename _Head>
78b1e83836Smrg    struct _Head_base<_Idx, _Head, true>
79b1e83836Smrg    {
80b1e83836Smrg      constexpr _Head_base()
81b1e83836Smrg      : _M_head_impl() { }
82b1e83836Smrg
83b1e83836Smrg      constexpr _Head_base(const _Head& __h)
84b1e83836Smrg      : _M_head_impl(__h) { }
85b1e83836Smrg
86b1e83836Smrg      constexpr _Head_base(const _Head_base&) = default;
87b1e83836Smrg      constexpr _Head_base(_Head_base&&) = default;
88b1e83836Smrg
89b1e83836Smrg      template<typename _UHead>
90b1e83836Smrg	constexpr _Head_base(_UHead&& __h)
91b1e83836Smrg	: _M_head_impl(std::forward<_UHead>(__h)) { }
92b1e83836Smrg
93b1e83836Smrg      _GLIBCXX20_CONSTEXPR
94b1e83836Smrg      _Head_base(allocator_arg_t, __uses_alloc0)
95b1e83836Smrg      : _M_head_impl() { }
96b1e83836Smrg
97b1e83836Smrg      template<typename _Alloc>
98b1e83836Smrg	_GLIBCXX20_CONSTEXPR
99b1e83836Smrg	_Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
100b1e83836Smrg	: _M_head_impl(allocator_arg, *__a._M_a) { }
101b1e83836Smrg
102b1e83836Smrg      template<typename _Alloc>
103b1e83836Smrg	_GLIBCXX20_CONSTEXPR
104b1e83836Smrg	_Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
105b1e83836Smrg	: _M_head_impl(*__a._M_a) { }
106b1e83836Smrg
107b1e83836Smrg      template<typename _UHead>
108b1e83836Smrg	_GLIBCXX20_CONSTEXPR
109b1e83836Smrg	_Head_base(__uses_alloc0, _UHead&& __uhead)
110b1e83836Smrg	: _M_head_impl(std::forward<_UHead>(__uhead)) { }
111b1e83836Smrg
112b1e83836Smrg      template<typename _Alloc, typename _UHead>
113b1e83836Smrg	_GLIBCXX20_CONSTEXPR
114b1e83836Smrg	_Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
115b1e83836Smrg	: _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
116b1e83836Smrg	{ }
117b1e83836Smrg
118b1e83836Smrg      template<typename _Alloc, typename _UHead>
119b1e83836Smrg	_GLIBCXX20_CONSTEXPR
120b1e83836Smrg	_Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
121b1e83836Smrg	: _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
122b1e83836Smrg
123b1e83836Smrg      static constexpr _Head&
124b1e83836Smrg      _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
125b1e83836Smrg
126b1e83836Smrg      static constexpr const _Head&
127b1e83836Smrg      _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
128b1e83836Smrg
129b1e83836Smrg      [[__no_unique_address__]] _Head _M_head_impl;
130b1e83836Smrg    };
131b1e83836Smrg#else
132b1e83836Smrg  template<size_t _Idx, typename _Head>
1334fee23f9Smrg    struct _Head_base<_Idx, _Head, true>
1344fee23f9Smrg    : public _Head
1354fee23f9Smrg    {
13648fb7bfaSmrg      constexpr _Head_base()
1374fee23f9Smrg      : _Head() { }
1384fee23f9Smrg
13948fb7bfaSmrg      constexpr _Head_base(const _Head& __h)
1404fee23f9Smrg      : _Head(__h) { }
1414fee23f9Smrg
1426012017cSmrg      constexpr _Head_base(const _Head_base&) = default;
1436012017cSmrg      constexpr _Head_base(_Head_base&&) = default;
1446012017cSmrg
1456012017cSmrg      template<typename _UHead>
14648fb7bfaSmrg        constexpr _Head_base(_UHead&& __h)
1474fee23f9Smrg	: _Head(std::forward<_UHead>(__h)) { }
1484fee23f9Smrg
149a448f87cSmrg      _GLIBCXX20_CONSTEXPR
1506012017cSmrg      _Head_base(allocator_arg_t, __uses_alloc0)
15148fb7bfaSmrg      : _Head() { }
1524fee23f9Smrg
15348fb7bfaSmrg      template<typename _Alloc>
154a448f87cSmrg	_GLIBCXX20_CONSTEXPR
1556012017cSmrg	_Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
15648fb7bfaSmrg	: _Head(allocator_arg, *__a._M_a) { }
15748fb7bfaSmrg
15848fb7bfaSmrg      template<typename _Alloc>
159a448f87cSmrg	_GLIBCXX20_CONSTEXPR
1606012017cSmrg	_Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
16148fb7bfaSmrg	: _Head(*__a._M_a) { }
16248fb7bfaSmrg
16348fb7bfaSmrg      template<typename _UHead>
164a448f87cSmrg	_GLIBCXX20_CONSTEXPR
16548fb7bfaSmrg	_Head_base(__uses_alloc0, _UHead&& __uhead)
16648fb7bfaSmrg	: _Head(std::forward<_UHead>(__uhead)) { }
16748fb7bfaSmrg
16848fb7bfaSmrg      template<typename _Alloc, typename _UHead>
169a448f87cSmrg	_GLIBCXX20_CONSTEXPR
17048fb7bfaSmrg	_Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
17148fb7bfaSmrg	: _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
17248fb7bfaSmrg
17348fb7bfaSmrg      template<typename _Alloc, typename _UHead>
174a448f87cSmrg	_GLIBCXX20_CONSTEXPR
17548fb7bfaSmrg	_Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
17648fb7bfaSmrg	: _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
17748fb7bfaSmrg
17848fb7bfaSmrg      static constexpr _Head&
17948fb7bfaSmrg      _M_head(_Head_base& __b) noexcept { return __b; }
18048fb7bfaSmrg
18148fb7bfaSmrg      static constexpr const _Head&
18248fb7bfaSmrg      _M_head(const _Head_base& __b) noexcept { return __b; }
1834fee23f9Smrg    };
184b1e83836Smrg#endif
1854fee23f9Smrg
186b1e83836Smrg  template<size_t _Idx, typename _Head>
1874fee23f9Smrg    struct _Head_base<_Idx, _Head, false>
1884fee23f9Smrg    {
18948fb7bfaSmrg      constexpr _Head_base()
1904fee23f9Smrg      : _M_head_impl() { }
1914fee23f9Smrg
19248fb7bfaSmrg      constexpr _Head_base(const _Head& __h)
1934fee23f9Smrg      : _M_head_impl(__h) { }
1944fee23f9Smrg
1956012017cSmrg      constexpr _Head_base(const _Head_base&) = default;
1966012017cSmrg      constexpr _Head_base(_Head_base&&) = default;
1976012017cSmrg
1986012017cSmrg      template<typename _UHead>
19948fb7bfaSmrg        constexpr _Head_base(_UHead&& __h)
2004fee23f9Smrg	: _M_head_impl(std::forward<_UHead>(__h)) { }
2014fee23f9Smrg
202fb8a8121Smrg      _GLIBCXX20_CONSTEXPR
2036012017cSmrg      _Head_base(allocator_arg_t, __uses_alloc0)
20448fb7bfaSmrg      : _M_head_impl() { }
2054fee23f9Smrg
20648fb7bfaSmrg      template<typename _Alloc>
207a448f87cSmrg	_GLIBCXX20_CONSTEXPR
2086012017cSmrg	_Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
20948fb7bfaSmrg	: _M_head_impl(allocator_arg, *__a._M_a) { }
21048fb7bfaSmrg
21148fb7bfaSmrg      template<typename _Alloc>
212a448f87cSmrg	_GLIBCXX20_CONSTEXPR
2136012017cSmrg	_Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
21448fb7bfaSmrg	: _M_head_impl(*__a._M_a) { }
21548fb7bfaSmrg
21648fb7bfaSmrg      template<typename _UHead>
217fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
21848fb7bfaSmrg	_Head_base(__uses_alloc0, _UHead&& __uhead)
21948fb7bfaSmrg	: _M_head_impl(std::forward<_UHead>(__uhead)) { }
22048fb7bfaSmrg
22148fb7bfaSmrg      template<typename _Alloc, typename _UHead>
222a448f87cSmrg	_GLIBCXX20_CONSTEXPR
22348fb7bfaSmrg	_Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
22448fb7bfaSmrg	: _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
22548fb7bfaSmrg	{ }
22648fb7bfaSmrg
22748fb7bfaSmrg      template<typename _Alloc, typename _UHead>
228a448f87cSmrg	_GLIBCXX20_CONSTEXPR
22948fb7bfaSmrg	_Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
23048fb7bfaSmrg	: _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
23148fb7bfaSmrg
23248fb7bfaSmrg      static constexpr _Head&
23348fb7bfaSmrg      _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
23448fb7bfaSmrg
23548fb7bfaSmrg      static constexpr const _Head&
23648fb7bfaSmrg      _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
2374fee23f9Smrg
2384fee23f9Smrg      _Head _M_head_impl;
2394fee23f9Smrg    };
2404fee23f9Smrg
2414fee23f9Smrg  /**
2424fee23f9Smrg   * Contains the actual implementation of the @c tuple template, stored
2434fee23f9Smrg   * as a recursive inheritance hierarchy from the first element (most
2444fee23f9Smrg   * derived class) to the last (least derived class). The @c Idx
2454fee23f9Smrg   * parameter gives the 0-based index of the element stored at this
2464fee23f9Smrg   * point in the hierarchy; we use it to implement a constant-time
2474fee23f9Smrg   * get() operation.
2484fee23f9Smrg   */
249b1e83836Smrg  template<size_t _Idx, typename... _Elements>
2504fee23f9Smrg    struct _Tuple_impl;
2514fee23f9Smrg
2524fee23f9Smrg  /**
2534fee23f9Smrg   * Recursive tuple implementation. Here we store the @c Head element
2544fee23f9Smrg   * and derive from a @c Tuple_impl containing the remaining elements
2554fee23f9Smrg   * (which contains the @c Tail).
2564fee23f9Smrg   */
257b1e83836Smrg  template<size_t _Idx, typename _Head, typename... _Tail>
2584fee23f9Smrg    struct _Tuple_impl<_Idx, _Head, _Tail...>
2594fee23f9Smrg    : public _Tuple_impl<_Idx + 1, _Tail...>,
260b17d1066Smrg      private _Head_base<_Idx, _Head>
2614fee23f9Smrg    {
262b1e83836Smrg      template<size_t, typename...> friend struct _Tuple_impl;
26348fb7bfaSmrg
2644fee23f9Smrg      typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
265b17d1066Smrg      typedef _Head_base<_Idx, _Head> _Base;
2664fee23f9Smrg
26748fb7bfaSmrg      static constexpr _Head&
26848fb7bfaSmrg      _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
2694fee23f9Smrg
27048fb7bfaSmrg      static constexpr const _Head&
27148fb7bfaSmrg      _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
2724fee23f9Smrg
27348fb7bfaSmrg      static constexpr _Inherited&
27448fb7bfaSmrg      _M_tail(_Tuple_impl& __t) noexcept { return __t; }
27548fb7bfaSmrg
27648fb7bfaSmrg      static constexpr const _Inherited&
27748fb7bfaSmrg      _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
27848fb7bfaSmrg
27948fb7bfaSmrg      constexpr _Tuple_impl()
2804fee23f9Smrg      : _Inherited(), _Base() { }
2814fee23f9Smrg
282b1e83836Smrg      explicit constexpr
283b1e83836Smrg      _Tuple_impl(const _Head& __head, const _Tail&... __tail)
284b1e83836Smrg      : _Inherited(__tail...), _Base(__head)
285b1e83836Smrg      { }
2864fee23f9Smrg
287b1e83836Smrg      template<typename _UHead, typename... _UTail,
288b1e83836Smrg	       typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
289b1e83836Smrg	explicit constexpr
290b1e83836Smrg	_Tuple_impl(_UHead&& __head, _UTail&&... __tail)
2914fee23f9Smrg	: _Inherited(std::forward<_UTail>(__tail)...),
292b1e83836Smrg	  _Base(std::forward<_UHead>(__head))
293b1e83836Smrg	{ }
2944fee23f9Smrg
29548fb7bfaSmrg      constexpr _Tuple_impl(const _Tuple_impl&) = default;
2964fee23f9Smrg
297181254a7Smrg      // _GLIBCXX_RESOLVE_LIB_DEFECTS
298181254a7Smrg      // 2729. Missing SFINAE on std::pair::operator=
299181254a7Smrg      _Tuple_impl& operator=(const _Tuple_impl&) = delete;
300181254a7Smrg
301b1e83836Smrg      _Tuple_impl(_Tuple_impl&&) = default;
3024fee23f9Smrg
3034fee23f9Smrg      template<typename... _UElements>
304b1e83836Smrg	constexpr
305b1e83836Smrg	_Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
30648fb7bfaSmrg	: _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
307b1e83836Smrg	  _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
308b1e83836Smrg	{ }
3094fee23f9Smrg
31048fb7bfaSmrg      template<typename _UHead, typename... _UTails>
311b1e83836Smrg	constexpr
312b1e83836Smrg	_Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
31348fb7bfaSmrg	: _Inherited(std::move
31448fb7bfaSmrg		     (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
31548fb7bfaSmrg	  _Base(std::forward<_UHead>
316b1e83836Smrg		(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
317b1e83836Smrg	{ }
31848fb7bfaSmrg
31948fb7bfaSmrg      template<typename _Alloc>
320fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
32148fb7bfaSmrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
32248fb7bfaSmrg	: _Inherited(__tag, __a),
323b1e83836Smrg	  _Base(__tag, __use_alloc<_Head>(__a))
324b1e83836Smrg	{ }
32548fb7bfaSmrg
32648fb7bfaSmrg      template<typename _Alloc>
327a448f87cSmrg	_GLIBCXX20_CONSTEXPR
32848fb7bfaSmrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
32948fb7bfaSmrg		    const _Head& __head, const _Tail&... __tail)
33048fb7bfaSmrg	: _Inherited(__tag, __a, __tail...),
331b1e83836Smrg	  _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
332b1e83836Smrg	{ }
33348fb7bfaSmrg
33448fb7bfaSmrg      template<typename _Alloc, typename _UHead, typename... _UTail,
335b1e83836Smrg	       typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
336fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
33748fb7bfaSmrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
33848fb7bfaSmrg		    _UHead&& __head, _UTail&&... __tail)
33948fb7bfaSmrg	: _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
34048fb7bfaSmrg	  _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
341b1e83836Smrg		std::forward<_UHead>(__head))
342b1e83836Smrg	{ }
34348fb7bfaSmrg
34448fb7bfaSmrg      template<typename _Alloc>
345fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
34648fb7bfaSmrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
34748fb7bfaSmrg		    const _Tuple_impl& __in)
34848fb7bfaSmrg	: _Inherited(__tag, __a, _M_tail(__in)),
349b1e83836Smrg	  _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
350b1e83836Smrg	{ }
35148fb7bfaSmrg
35248fb7bfaSmrg      template<typename _Alloc>
353fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
35448fb7bfaSmrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
35548fb7bfaSmrg		    _Tuple_impl&& __in)
35648fb7bfaSmrg	: _Inherited(__tag, __a, std::move(_M_tail(__in))),
35748fb7bfaSmrg	  _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
358b1e83836Smrg		std::forward<_Head>(_M_head(__in)))
359b1e83836Smrg	{ }
36048fb7bfaSmrg
361fb8a8121Smrg      template<typename _Alloc, typename _UHead, typename... _UTails>
362fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
36348fb7bfaSmrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
364fb8a8121Smrg		    const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
36548fb7bfaSmrg	: _Inherited(__tag, __a,
366fb8a8121Smrg		     _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
367fb8a8121Smrg	  _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
368b1e83836Smrg		_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
369b1e83836Smrg	{ }
37048fb7bfaSmrg
37148fb7bfaSmrg      template<typename _Alloc, typename _UHead, typename... _UTails>
372fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
37348fb7bfaSmrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
37448fb7bfaSmrg		    _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
37548fb7bfaSmrg	: _Inherited(__tag, __a, std::move
37648fb7bfaSmrg		     (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
37748fb7bfaSmrg	  _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
37848fb7bfaSmrg		std::forward<_UHead>
379b1e83836Smrg		(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
380b1e83836Smrg	{ }
3814fee23f9Smrg
3824fee23f9Smrg      template<typename... _UElements>
383fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
384181254a7Smrg	void
385181254a7Smrg	_M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
3864fee23f9Smrg	{
38748fb7bfaSmrg	  _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
388181254a7Smrg	  _M_tail(*this)._M_assign(
389181254a7Smrg	      _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
3904fee23f9Smrg	}
3914fee23f9Smrg
39248fb7bfaSmrg      template<typename _UHead, typename... _UTails>
393fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
394181254a7Smrg	void
395181254a7Smrg	_M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
3964fee23f9Smrg	{
39748fb7bfaSmrg	  _M_head(*this) = std::forward<_UHead>
39848fb7bfaSmrg	    (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
399181254a7Smrg	  _M_tail(*this)._M_assign(
400181254a7Smrg	      std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
4014fee23f9Smrg	}
4024fee23f9Smrg
4034fee23f9Smrg    protected:
404fb8a8121Smrg      _GLIBCXX20_CONSTEXPR
4054fee23f9Smrg      void
40648fb7bfaSmrg      _M_swap(_Tuple_impl& __in)
4074fee23f9Smrg      {
40848fb7bfaSmrg	using std::swap;
40948fb7bfaSmrg	swap(_M_head(*this), _M_head(__in));
41048fb7bfaSmrg	_Inherited::_M_swap(_M_tail(__in));
4114fee23f9Smrg      }
4124fee23f9Smrg    };
4134fee23f9Smrg
4144d5abbe8Smrg  // Basis case of inheritance recursion.
415b1e83836Smrg  template<size_t _Idx, typename _Head>
4164d5abbe8Smrg    struct _Tuple_impl<_Idx, _Head>
417b17d1066Smrg    : private _Head_base<_Idx, _Head>
4184d5abbe8Smrg    {
419b1e83836Smrg      template<size_t, typename...> friend struct _Tuple_impl;
4204d5abbe8Smrg
421b17d1066Smrg      typedef _Head_base<_Idx, _Head> _Base;
4224d5abbe8Smrg
4234d5abbe8Smrg      static constexpr _Head&
4244d5abbe8Smrg      _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
4254d5abbe8Smrg
4264d5abbe8Smrg      static constexpr const _Head&
4274d5abbe8Smrg      _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
4284d5abbe8Smrg
429b1e83836Smrg      constexpr
430b1e83836Smrg      _Tuple_impl()
4314d5abbe8Smrg      : _Base() { }
4324d5abbe8Smrg
433b1e83836Smrg      explicit constexpr
434b1e83836Smrg      _Tuple_impl(const _Head& __head)
435b1e83836Smrg      : _Base(__head)
436b1e83836Smrg      { }
4374d5abbe8Smrg
4384d5abbe8Smrg      template<typename _UHead>
439b1e83836Smrg	explicit constexpr
440b1e83836Smrg	_Tuple_impl(_UHead&& __head)
441b1e83836Smrg	: _Base(std::forward<_UHead>(__head))
442b1e83836Smrg	{ }
4434d5abbe8Smrg
4444d5abbe8Smrg      constexpr _Tuple_impl(const _Tuple_impl&) = default;
4454d5abbe8Smrg
446181254a7Smrg      // _GLIBCXX_RESOLVE_LIB_DEFECTS
447181254a7Smrg      // 2729. Missing SFINAE on std::pair::operator=
448181254a7Smrg      _Tuple_impl& operator=(const _Tuple_impl&) = delete;
449181254a7Smrg
450b1e83836Smrg#if _GLIBCXX_INLINE_VERSION
451b1e83836Smrg      _Tuple_impl(_Tuple_impl&&) = default;
452b1e83836Smrg#else
4534d5abbe8Smrg      constexpr
4544d5abbe8Smrg      _Tuple_impl(_Tuple_impl&& __in)
4554d5abbe8Smrg      noexcept(is_nothrow_move_constructible<_Head>::value)
456b1e83836Smrg      : _Base(static_cast<_Base&&>(__in))
457b1e83836Smrg      { }
458b1e83836Smrg#endif
4594d5abbe8Smrg
4604d5abbe8Smrg      template<typename _UHead>
461b1e83836Smrg	constexpr
462b1e83836Smrg	_Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
463b1e83836Smrg	: _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
464b1e83836Smrg	{ }
4654d5abbe8Smrg
4664d5abbe8Smrg      template<typename _UHead>
467b1e83836Smrg	constexpr
468b1e83836Smrg	_Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
4694d5abbe8Smrg	: _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
4704d5abbe8Smrg	{ }
4714d5abbe8Smrg
4724d5abbe8Smrg      template<typename _Alloc>
473fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
4744d5abbe8Smrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
475b1e83836Smrg	: _Base(__tag, __use_alloc<_Head>(__a))
476b1e83836Smrg	{ }
4774d5abbe8Smrg
4784d5abbe8Smrg      template<typename _Alloc>
479a448f87cSmrg	_GLIBCXX20_CONSTEXPR
4804d5abbe8Smrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
4814d5abbe8Smrg		    const _Head& __head)
482b1e83836Smrg	: _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
483b1e83836Smrg	{ }
4844d5abbe8Smrg
4854d5abbe8Smrg      template<typename _Alloc, typename _UHead>
486fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
4874d5abbe8Smrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
4884d5abbe8Smrg		    _UHead&& __head)
4894d5abbe8Smrg	: _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
490b1e83836Smrg		std::forward<_UHead>(__head))
491b1e83836Smrg	{ }
4924d5abbe8Smrg
4934d5abbe8Smrg      template<typename _Alloc>
494fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
4954d5abbe8Smrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
4964d5abbe8Smrg		    const _Tuple_impl& __in)
497b1e83836Smrg	: _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
498b1e83836Smrg	{ }
4994d5abbe8Smrg
5004d5abbe8Smrg      template<typename _Alloc>
501fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
5024d5abbe8Smrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
5034d5abbe8Smrg		    _Tuple_impl&& __in)
5044d5abbe8Smrg	: _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
505b1e83836Smrg		std::forward<_Head>(_M_head(__in)))
506b1e83836Smrg	{ }
5074d5abbe8Smrg
5084d5abbe8Smrg      template<typename _Alloc, typename _UHead>
509fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
5104d5abbe8Smrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
5114d5abbe8Smrg		    const _Tuple_impl<_Idx, _UHead>& __in)
512fb8a8121Smrg	: _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
513b1e83836Smrg		_Tuple_impl<_Idx, _UHead>::_M_head(__in))
514b1e83836Smrg	{ }
5154d5abbe8Smrg
5164d5abbe8Smrg      template<typename _Alloc, typename _UHead>
517fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
5184d5abbe8Smrg	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
5194d5abbe8Smrg		    _Tuple_impl<_Idx, _UHead>&& __in)
5204d5abbe8Smrg	: _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
5214d5abbe8Smrg		std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
5224d5abbe8Smrg	{ }
5234d5abbe8Smrg
5244d5abbe8Smrg      template<typename _UHead>
525fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
526181254a7Smrg	void
527181254a7Smrg	_M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
5284d5abbe8Smrg	{
5294d5abbe8Smrg	  _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
5304d5abbe8Smrg	}
5314d5abbe8Smrg
5324d5abbe8Smrg      template<typename _UHead>
533fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
534181254a7Smrg	void
535181254a7Smrg	_M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
5364d5abbe8Smrg	{
5374d5abbe8Smrg	  _M_head(*this)
5384d5abbe8Smrg	    = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
5394d5abbe8Smrg	}
5404d5abbe8Smrg
5414d5abbe8Smrg    protected:
542fb8a8121Smrg      _GLIBCXX20_CONSTEXPR
5434d5abbe8Smrg      void
5444d5abbe8Smrg      _M_swap(_Tuple_impl& __in)
5454d5abbe8Smrg      {
5464d5abbe8Smrg	using std::swap;
5474d5abbe8Smrg	swap(_M_head(*this), _M_head(__in));
5484d5abbe8Smrg      }
5494d5abbe8Smrg    };
5504d5abbe8Smrg
551f9a78e0eSmrg  // Concept utility functions, reused in conditionally-explicit
552f9a78e0eSmrg  // constructors.
553fb8a8121Smrg  template<bool, typename... _Types>
554fb8a8121Smrg    struct _TupleConstraints
555f9a78e0eSmrg    {
556fb8a8121Smrg      // Constraint for a non-explicit constructor.
557fb8a8121Smrg      // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
558fb8a8121Smrg      // and every Ui is implicitly convertible to Ti.
559fb8a8121Smrg      template<typename... _UTypes>
560fb8a8121Smrg	static constexpr bool __is_implicitly_constructible()
561f9a78e0eSmrg	{
562fb8a8121Smrg	  return __and_<is_constructible<_Types, _UTypes>...,
563fb8a8121Smrg			is_convertible<_UTypes, _Types>...
564f9a78e0eSmrg			>::value;
565f9a78e0eSmrg	}
566181254a7Smrg
567fb8a8121Smrg      // Constraint for a non-explicit constructor.
568fb8a8121Smrg      // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
569fb8a8121Smrg      // but not every Ui is implicitly convertible to Ti.
570fb8a8121Smrg      template<typename... _UTypes>
571fb8a8121Smrg	static constexpr bool __is_explicitly_constructible()
572f9a78e0eSmrg	{
573fb8a8121Smrg	  return __and_<is_constructible<_Types, _UTypes>...,
574fb8a8121Smrg			__not_<__and_<is_convertible<_UTypes, _Types>...>>
575fb8a8121Smrg			>::value;
576fb8a8121Smrg	}
577fb8a8121Smrg
578fb8a8121Smrg      static constexpr bool __is_implicitly_default_constructible()
579fb8a8121Smrg      {
580fb8a8121Smrg	return __and_<std::__is_implicitly_default_constructible<_Types>...
581fb8a8121Smrg		      >::value;
582fb8a8121Smrg      }
583fb8a8121Smrg
584fb8a8121Smrg      static constexpr bool __is_explicitly_default_constructible()
585fb8a8121Smrg      {
586fb8a8121Smrg	return __and_<is_default_constructible<_Types>...,
587fb8a8121Smrg		      __not_<__and_<
588fb8a8121Smrg			std::__is_implicitly_default_constructible<_Types>...>
589fb8a8121Smrg		      >>::value;
590f9a78e0eSmrg      }
591f9a78e0eSmrg    };
592f9a78e0eSmrg
593fb8a8121Smrg  // Partial specialization used when a required precondition isn't met,
594fb8a8121Smrg  // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
595fb8a8121Smrg  template<typename... _Types>
596fb8a8121Smrg    struct _TupleConstraints<false, _Types...>
597f9a78e0eSmrg    {
598fb8a8121Smrg      template<typename... _UTypes>
599fb8a8121Smrg	static constexpr bool __is_implicitly_constructible()
600fb8a8121Smrg	{ return false; }
601f9a78e0eSmrg
602fb8a8121Smrg      template<typename... _UTypes>
603fb8a8121Smrg	static constexpr bool __is_explicitly_constructible()
604fb8a8121Smrg	{ return false; }
605f9a78e0eSmrg    };
606f9a78e0eSmrg
60748fb7bfaSmrg  /// Primary class template, tuple
6084fee23f9Smrg  template<typename... _Elements>
6094fee23f9Smrg    class tuple : public _Tuple_impl<0, _Elements...>
6104fee23f9Smrg    {
6114fee23f9Smrg      typedef _Tuple_impl<0, _Elements...> _Inherited;
6124fee23f9Smrg
613fb8a8121Smrg      template<bool _Cond>
614fb8a8121Smrg	using _TCC = _TupleConstraints<_Cond, _Elements...>;
615fb8a8121Smrg
616fb8a8121Smrg      // Constraint for non-explicit default constructor
617fb8a8121Smrg      template<bool _Dummy>
618fb8a8121Smrg	using _ImplicitDefaultCtor = __enable_if_t<
619fb8a8121Smrg	  _TCC<_Dummy>::__is_implicitly_default_constructible(),
620fb8a8121Smrg	  bool>;
621fb8a8121Smrg
622fb8a8121Smrg      // Constraint for explicit default constructor
623fb8a8121Smrg      template<bool _Dummy>
624fb8a8121Smrg	using _ExplicitDefaultCtor = __enable_if_t<
625fb8a8121Smrg	  _TCC<_Dummy>::__is_explicitly_default_constructible(),
626fb8a8121Smrg	  bool>;
627fb8a8121Smrg
628fb8a8121Smrg      // Constraint for non-explicit constructors
629fb8a8121Smrg      template<bool _Cond, typename... _Args>
630fb8a8121Smrg	using _ImplicitCtor = __enable_if_t<
631fb8a8121Smrg	  _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
632fb8a8121Smrg	  bool>;
633fb8a8121Smrg
634fb8a8121Smrg      // Constraint for non-explicit constructors
635fb8a8121Smrg      template<bool _Cond, typename... _Args>
636fb8a8121Smrg	using _ExplicitCtor = __enable_if_t<
637fb8a8121Smrg	  _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
638fb8a8121Smrg	  bool>;
639f9a78e0eSmrg
640181254a7Smrg      template<typename... _UElements>
641181254a7Smrg	static constexpr
642181254a7Smrg	__enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
643181254a7Smrg	__assignable()
644181254a7Smrg	{ return __and_<is_assignable<_Elements&, _UElements>...>::value; }
645181254a7Smrg
646fb8a8121Smrg      // Condition for noexcept-specifier of an assignment operator.
647181254a7Smrg      template<typename... _UElements>
648181254a7Smrg	static constexpr bool __nothrow_assignable()
649181254a7Smrg	{
650181254a7Smrg	  return
651181254a7Smrg	    __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
652181254a7Smrg	}
653181254a7Smrg
654fb8a8121Smrg      // Condition for noexcept-specifier of a constructor.
655fb8a8121Smrg      template<typename... _UElements>
656fb8a8121Smrg	static constexpr bool __nothrow_constructible()
657fb8a8121Smrg	{
658fb8a8121Smrg	  return
659fb8a8121Smrg	    __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
660fb8a8121Smrg	}
661fb8a8121Smrg
662fb8a8121Smrg      // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
663fb8a8121Smrg      template<typename _Up>
664fb8a8121Smrg	static constexpr bool __valid_args()
665fb8a8121Smrg	{
666fb8a8121Smrg	  return sizeof...(_Elements) == 1
667fb8a8121Smrg	    && !is_same<tuple, __remove_cvref_t<_Up>>::value;
668fb8a8121Smrg	}
669fb8a8121Smrg
670fb8a8121Smrg      // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
671fb8a8121Smrg      template<typename, typename, typename... _Tail>
672fb8a8121Smrg	static constexpr bool __valid_args()
673fb8a8121Smrg	{ return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
674fb8a8121Smrg
675fb8a8121Smrg      /* Constraint for constructors with a tuple<UTypes...> parameter ensures
676fb8a8121Smrg       * that the constructor is only viable when it would not interfere with
677fb8a8121Smrg       * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
678fb8a8121Smrg       * Such constructors are only viable if:
679fb8a8121Smrg       * either sizeof...(Types) != 1,
680fb8a8121Smrg       * or (when Types... expands to T and UTypes... expands to U)
681fb8a8121Smrg       * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
682fb8a8121Smrg       * and is_same_v<T, U> are all false.
683fb8a8121Smrg       */
684fb8a8121Smrg      template<typename _Tuple, typename = tuple,
685fb8a8121Smrg	       typename = __remove_cvref_t<_Tuple>>
686fb8a8121Smrg	struct _UseOtherCtor
687fb8a8121Smrg	: false_type
688fb8a8121Smrg	{ };
689fb8a8121Smrg      // If TUPLE is convertible to the single element in *this,
690fb8a8121Smrg      // then TUPLE should match tuple(UTypes&&...) instead.
691fb8a8121Smrg      template<typename _Tuple, typename _Tp, typename _Up>
692fb8a8121Smrg	struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
693fb8a8121Smrg	: __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>
694fb8a8121Smrg	{ };
695fb8a8121Smrg      // If TUPLE and *this each have a single element of the same type,
696fb8a8121Smrg      // then TUPLE should match a copy/move constructor instead.
697fb8a8121Smrg      template<typename _Tuple, typename _Tp>
698fb8a8121Smrg	struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
699fb8a8121Smrg	: true_type
700fb8a8121Smrg	{ };
701fb8a8121Smrg
702fb8a8121Smrg      // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
703fb8a8121Smrg      // and the single element in Types can be initialized from TUPLE,
704fb8a8121Smrg      // or is the same type as tuple_element_t<0, TUPLE>.
705fb8a8121Smrg      template<typename _Tuple>
706fb8a8121Smrg	static constexpr bool __use_other_ctor()
707fb8a8121Smrg	{ return _UseOtherCtor<_Tuple>::value; }
708fb8a8121Smrg
7094fee23f9Smrg    public:
710f9a78e0eSmrg      template<typename _Dummy = void,
711fb8a8121Smrg	       _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
712fb8a8121Smrg	constexpr
713fb8a8121Smrg	tuple()
714fb8a8121Smrg	noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
7154fee23f9Smrg	: _Inherited() { }
7164fee23f9Smrg
717f9a78e0eSmrg      template<typename _Dummy = void,
718fb8a8121Smrg	       _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
719fb8a8121Smrg	explicit constexpr
720fb8a8121Smrg	tuple()
721fb8a8121Smrg	noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
722f9a78e0eSmrg	: _Inherited() { }
723f9a78e0eSmrg
724fb8a8121Smrg      template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
725fb8a8121Smrg	       _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
726fb8a8121Smrg	constexpr
727fb8a8121Smrg	tuple(const _Elements&... __elements)
728fb8a8121Smrg	noexcept(__nothrow_constructible<const _Elements&...>())
7294fee23f9Smrg	: _Inherited(__elements...) { }
7304fee23f9Smrg
731fb8a8121Smrg      template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
732fb8a8121Smrg	       _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
733fb8a8121Smrg	explicit constexpr
734fb8a8121Smrg	tuple(const _Elements&... __elements)
735fb8a8121Smrg	noexcept(__nothrow_constructible<const _Elements&...>())
736f9a78e0eSmrg	: _Inherited(__elements...) { }
737f9a78e0eSmrg
738fb8a8121Smrg      template<typename... _UElements,
739fb8a8121Smrg	       bool _Valid = __valid_args<_UElements...>(),
740fb8a8121Smrg	       _ImplicitCtor<_Valid, _UElements...> = true>
741fb8a8121Smrg	constexpr
742fb8a8121Smrg	tuple(_UElements&&... __elements)
743fb8a8121Smrg	noexcept(__nothrow_constructible<_UElements...>())
7444fee23f9Smrg	: _Inherited(std::forward<_UElements>(__elements)...) { }
7454fee23f9Smrg
746fb8a8121Smrg      template<typename... _UElements,
747fb8a8121Smrg	       bool _Valid = __valid_args<_UElements...>(),
748fb8a8121Smrg	       _ExplicitCtor<_Valid, _UElements...> = false>
749fb8a8121Smrg	explicit constexpr
750fb8a8121Smrg	tuple(_UElements&&... __elements)
751fb8a8121Smrg	noexcept(__nothrow_constructible<_UElements...>())
752f9a78e0eSmrg	: _Inherited(std::forward<_UElements>(__elements)...) {	}
753f9a78e0eSmrg
75448fb7bfaSmrg      constexpr tuple(const tuple&) = default;
7554fee23f9Smrg
75648fb7bfaSmrg      constexpr tuple(tuple&&) = default;
7574fee23f9Smrg
758fb8a8121Smrg      template<typename... _UElements,
759fb8a8121Smrg	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
760fb8a8121Smrg			   && !__use_other_ctor<const tuple<_UElements...>&>(),
761fb8a8121Smrg	       _ImplicitCtor<_Valid, const _UElements&...> = true>
762fb8a8121Smrg	constexpr
763fb8a8121Smrg	tuple(const tuple<_UElements...>& __in)
764fb8a8121Smrg	noexcept(__nothrow_constructible<const _UElements&...>())
7654fee23f9Smrg	: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
7664fee23f9Smrg	{ }
7674fee23f9Smrg
768fb8a8121Smrg      template<typename... _UElements,
769fb8a8121Smrg	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
770fb8a8121Smrg			   && !__use_other_ctor<const tuple<_UElements...>&>(),
771fb8a8121Smrg	       _ExplicitCtor<_Valid, const _UElements&...> = false>
772fb8a8121Smrg	explicit constexpr
773fb8a8121Smrg	tuple(const tuple<_UElements...>& __in)
774fb8a8121Smrg	noexcept(__nothrow_constructible<const _UElements&...>())
775f9a78e0eSmrg	: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
776f9a78e0eSmrg	{ }
777f9a78e0eSmrg
778fb8a8121Smrg      template<typename... _UElements,
779fb8a8121Smrg	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
780fb8a8121Smrg			     && !__use_other_ctor<tuple<_UElements...>&&>(),
781fb8a8121Smrg	       _ImplicitCtor<_Valid, _UElements...> = true>
782fb8a8121Smrg	constexpr
783fb8a8121Smrg	tuple(tuple<_UElements...>&& __in)
784fb8a8121Smrg	noexcept(__nothrow_constructible<_UElements...>())
7854fee23f9Smrg	: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
7864fee23f9Smrg
787fb8a8121Smrg      template<typename... _UElements,
788fb8a8121Smrg	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
789fb8a8121Smrg			     && !__use_other_ctor<tuple<_UElements...>&&>(),
790fb8a8121Smrg	       _ExplicitCtor<_Valid, _UElements...> = false>
791fb8a8121Smrg	explicit constexpr
792fb8a8121Smrg	tuple(tuple<_UElements...>&& __in)
793fb8a8121Smrg	noexcept(__nothrow_constructible<_UElements...>())
794f9a78e0eSmrg	: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
795f9a78e0eSmrg
79648fb7bfaSmrg      // Allocator-extended constructors.
79748fb7bfaSmrg
798fb8a8121Smrg      template<typename _Alloc,
799fb8a8121Smrg	       _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
800fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
80148fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a)
80248fb7bfaSmrg	: _Inherited(__tag, __a) { }
80348fb7bfaSmrg
804*0a307195Smrg      template<typename _Alloc,
805*0a307195Smrg	       _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
806*0a307195Smrg	_GLIBCXX20_CONSTEXPR
807*0a307195Smrg	explicit
808*0a307195Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a)
809*0a307195Smrg	: _Inherited(__tag, __a) { }
810*0a307195Smrg
811fb8a8121Smrg      template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
812fb8a8121Smrg	       _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
813fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
81448fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
81548fb7bfaSmrg	      const _Elements&... __elements)
81648fb7bfaSmrg	: _Inherited(__tag, __a, __elements...) { }
81748fb7bfaSmrg
818fb8a8121Smrg      template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
819fb8a8121Smrg	       _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
820fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
821fb8a8121Smrg	explicit
822fb8a8121Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
823f9a78e0eSmrg	      const _Elements&... __elements)
824f9a78e0eSmrg	: _Inherited(__tag, __a, __elements...) { }
825f9a78e0eSmrg
826fb8a8121Smrg      template<typename _Alloc, typename... _UElements,
827fb8a8121Smrg	       bool _Valid = __valid_args<_UElements...>(),
828fb8a8121Smrg	       _ImplicitCtor<_Valid, _UElements...> = true>
829fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
83048fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
83148fb7bfaSmrg	      _UElements&&... __elements)
83248fb7bfaSmrg	: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
83348fb7bfaSmrg	{ }
83448fb7bfaSmrg
835fb8a8121Smrg      template<typename _Alloc, typename... _UElements,
836fb8a8121Smrg		 bool _Valid = __valid_args<_UElements...>(),
837fb8a8121Smrg	       _ExplicitCtor<_Valid, _UElements...> = false>
838fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
839fb8a8121Smrg	explicit
840fb8a8121Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
841f9a78e0eSmrg	      _UElements&&... __elements)
842f9a78e0eSmrg	: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
843f9a78e0eSmrg	{ }
844f9a78e0eSmrg
84548fb7bfaSmrg      template<typename _Alloc>
846fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
84748fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
84848fb7bfaSmrg	: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
84948fb7bfaSmrg
85048fb7bfaSmrg      template<typename _Alloc>
851fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
85248fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
85348fb7bfaSmrg	: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
85448fb7bfaSmrg
855fb8a8121Smrg      template<typename _Alloc, typename... _UElements,
856fb8a8121Smrg	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
857fb8a8121Smrg			     && !__use_other_ctor<const tuple<_UElements...>&>(),
858fb8a8121Smrg	       _ImplicitCtor<_Valid, const _UElements&...> = true>
859fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
86048fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
86148fb7bfaSmrg	      const tuple<_UElements...>& __in)
86248fb7bfaSmrg	: _Inherited(__tag, __a,
86348fb7bfaSmrg	             static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
86448fb7bfaSmrg	{ }
86548fb7bfaSmrg
866fb8a8121Smrg      template<typename _Alloc, typename... _UElements,
867fb8a8121Smrg	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
868fb8a8121Smrg			     && !__use_other_ctor<const tuple<_UElements...>&>(),
869fb8a8121Smrg	       _ExplicitCtor<_Valid, const _UElements&...> = false>
870fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
871fb8a8121Smrg	explicit
872fb8a8121Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
873f9a78e0eSmrg	      const tuple<_UElements...>& __in)
874f9a78e0eSmrg	: _Inherited(__tag, __a,
875f9a78e0eSmrg	             static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
876f9a78e0eSmrg	{ }
877f9a78e0eSmrg
878fb8a8121Smrg      template<typename _Alloc, typename... _UElements,
879fb8a8121Smrg	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
880fb8a8121Smrg			     && !__use_other_ctor<tuple<_UElements...>&&>(),
881fb8a8121Smrg	       _ImplicitCtor<_Valid, _UElements...> = true>
882fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
88348fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
88448fb7bfaSmrg	      tuple<_UElements...>&& __in)
88548fb7bfaSmrg	: _Inherited(__tag, __a,
88648fb7bfaSmrg	             static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
8874fee23f9Smrg	{ }
8884fee23f9Smrg
889fb8a8121Smrg      template<typename _Alloc, typename... _UElements,
890fb8a8121Smrg	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
891fb8a8121Smrg			     && !__use_other_ctor<tuple<_UElements...>&&>(),
892fb8a8121Smrg	       _ExplicitCtor<_Valid, _UElements...> = false>
893fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
894fb8a8121Smrg	explicit
895fb8a8121Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
896f9a78e0eSmrg	      tuple<_UElements...>&& __in)
897f9a78e0eSmrg	: _Inherited(__tag, __a,
898f9a78e0eSmrg	             static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
899f9a78e0eSmrg	{ }
900f9a78e0eSmrg
901181254a7Smrg      // tuple assignment
902181254a7Smrg
903fb8a8121Smrg      _GLIBCXX20_CONSTEXPR
9044fee23f9Smrg      tuple&
905b1e83836Smrg      operator=(__conditional_t<__assignable<const _Elements&...>(),
906181254a7Smrg				const tuple&,
907b1e83836Smrg				const __nonesuch&> __in)
908181254a7Smrg      noexcept(__nothrow_assignable<const _Elements&...>())
9094fee23f9Smrg      {
910181254a7Smrg	this->_M_assign(__in);
9114fee23f9Smrg	return *this;
9124fee23f9Smrg      }
9134fee23f9Smrg
914fb8a8121Smrg      _GLIBCXX20_CONSTEXPR
9154fee23f9Smrg      tuple&
916b1e83836Smrg      operator=(__conditional_t<__assignable<_Elements...>(),
917181254a7Smrg				tuple&&,
918b1e83836Smrg				__nonesuch&&> __in)
919181254a7Smrg      noexcept(__nothrow_assignable<_Elements...>())
9204fee23f9Smrg      {
921181254a7Smrg	this->_M_assign(std::move(__in));
9224fee23f9Smrg	return *this;
9234fee23f9Smrg      }
9244fee23f9Smrg
925b17d1066Smrg      template<typename... _UElements>
926fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
927181254a7Smrg	__enable_if_t<__assignable<const _UElements&...>(), tuple&>
9284fee23f9Smrg	operator=(const tuple<_UElements...>& __in)
929181254a7Smrg	noexcept(__nothrow_assignable<const _UElements&...>())
9304fee23f9Smrg	{
931181254a7Smrg	  this->_M_assign(__in);
9324fee23f9Smrg	  return *this;
9334fee23f9Smrg	}
9344fee23f9Smrg
935b17d1066Smrg      template<typename... _UElements>
936fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
937181254a7Smrg	__enable_if_t<__assignable<_UElements...>(), tuple&>
9384fee23f9Smrg	operator=(tuple<_UElements...>&& __in)
939181254a7Smrg	noexcept(__nothrow_assignable<_UElements...>())
9404fee23f9Smrg	{
941181254a7Smrg	  this->_M_assign(std::move(__in));
9424fee23f9Smrg	  return *this;
9434fee23f9Smrg	}
9444fee23f9Smrg
945181254a7Smrg      // tuple swap
946fb8a8121Smrg      _GLIBCXX20_CONSTEXPR
9474fee23f9Smrg      void
9484fee23f9Smrg      swap(tuple& __in)
949181254a7Smrg      noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
95048fb7bfaSmrg      { _Inherited::_M_swap(__in); }
9514fee23f9Smrg    };
9524fee23f9Smrg
953b17d1066Smrg#if __cpp_deduction_guides >= 201606
954b17d1066Smrg  template<typename... _UTypes>
955b17d1066Smrg    tuple(_UTypes...) -> tuple<_UTypes...>;
956b17d1066Smrg  template<typename _T1, typename _T2>
957b17d1066Smrg    tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
958b17d1066Smrg  template<typename _Alloc, typename... _UTypes>
959b17d1066Smrg    tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
960b17d1066Smrg  template<typename _Alloc, typename _T1, typename _T2>
961b17d1066Smrg    tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
962b17d1066Smrg  template<typename _Alloc, typename... _UTypes>
963b17d1066Smrg    tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
964b17d1066Smrg#endif
965b17d1066Smrg
96648fb7bfaSmrg  // Explicit specialization, zero-element tuple.
9674fee23f9Smrg  template<>
9684fee23f9Smrg    class tuple<>
9694fee23f9Smrg    {
9704fee23f9Smrg    public:
971a448f87cSmrg      _GLIBCXX20_CONSTEXPR
97248fb7bfaSmrg      void swap(tuple&) noexcept { /* no-op */ }
973b17d1066Smrg      // We need the default since we're going to define no-op
974b17d1066Smrg      // allocator constructors.
975b17d1066Smrg      tuple() = default;
976b17d1066Smrg      // No-op allocator constructors.
977b17d1066Smrg      template<typename _Alloc>
978fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
979fb8a8121Smrg	tuple(allocator_arg_t, const _Alloc&) noexcept { }
980b17d1066Smrg      template<typename _Alloc>
981fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
982fb8a8121Smrg	tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
9834fee23f9Smrg    };
9844fee23f9Smrg
98548fb7bfaSmrg  /// Partial specialization, 2-element tuple.
98648fb7bfaSmrg  /// Includes construction and assignment from a pair.
9874fee23f9Smrg  template<typename _T1, typename _T2>
9884fee23f9Smrg    class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
9894fee23f9Smrg    {
9904fee23f9Smrg      typedef _Tuple_impl<0, _T1, _T2> _Inherited;
9914fee23f9Smrg
992fb8a8121Smrg      // Constraint for non-explicit default constructor
993fb8a8121Smrg      template<bool _Dummy, typename _U1, typename _U2>
994fb8a8121Smrg	using _ImplicitDefaultCtor = __enable_if_t<
995fb8a8121Smrg	  _TupleConstraints<_Dummy, _U1, _U2>::
996fb8a8121Smrg	    __is_implicitly_default_constructible(),
997fb8a8121Smrg	  bool>;
998fb8a8121Smrg
999fb8a8121Smrg      // Constraint for explicit default constructor
1000fb8a8121Smrg      template<bool _Dummy, typename _U1, typename _U2>
1001fb8a8121Smrg	using _ExplicitDefaultCtor = __enable_if_t<
1002fb8a8121Smrg	  _TupleConstraints<_Dummy, _U1, _U2>::
1003fb8a8121Smrg	    __is_explicitly_default_constructible(),
1004fb8a8121Smrg	  bool>;
1005fb8a8121Smrg
1006fb8a8121Smrg      template<bool _Dummy>
1007fb8a8121Smrg	using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
1008fb8a8121Smrg
1009fb8a8121Smrg      // Constraint for non-explicit constructors
1010fb8a8121Smrg      template<bool _Cond, typename _U1, typename _U2>
1011fb8a8121Smrg	using _ImplicitCtor = __enable_if_t<
1012fb8a8121Smrg	  _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
1013fb8a8121Smrg	  bool>;
1014fb8a8121Smrg
1015fb8a8121Smrg      // Constraint for non-explicit constructors
1016fb8a8121Smrg      template<bool _Cond, typename _U1, typename _U2>
1017fb8a8121Smrg	using _ExplicitCtor = __enable_if_t<
1018fb8a8121Smrg	  _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
1019fb8a8121Smrg	  bool>;
1020fb8a8121Smrg
1021181254a7Smrg      template<typename _U1, typename _U2>
1022181254a7Smrg	static constexpr bool __assignable()
1023181254a7Smrg	{
1024181254a7Smrg	  return __and_<is_assignable<_T1&, _U1>,
1025181254a7Smrg			is_assignable<_T2&, _U2>>::value;
1026181254a7Smrg	}
1027181254a7Smrg
1028181254a7Smrg      template<typename _U1, typename _U2>
1029181254a7Smrg	static constexpr bool __nothrow_assignable()
1030181254a7Smrg	{
1031181254a7Smrg	  return __and_<is_nothrow_assignable<_T1&, _U1>,
1032181254a7Smrg			is_nothrow_assignable<_T2&, _U2>>::value;
1033181254a7Smrg	}
1034181254a7Smrg
1035fb8a8121Smrg      template<typename _U1, typename _U2>
1036fb8a8121Smrg	static constexpr bool __nothrow_constructible()
1037fb8a8121Smrg	{
1038fb8a8121Smrg	  return __and_<is_nothrow_constructible<_T1, _U1>,
1039fb8a8121Smrg			    is_nothrow_constructible<_T2, _U2>>::value;
1040fb8a8121Smrg	}
1041fb8a8121Smrg
1042fb8a8121Smrg      static constexpr bool __nothrow_default_constructible()
1043fb8a8121Smrg      {
1044fb8a8121Smrg	return __and_<is_nothrow_default_constructible<_T1>,
1045fb8a8121Smrg		      is_nothrow_default_constructible<_T2>>::value;
1046fb8a8121Smrg      }
1047fb8a8121Smrg
1048fb8a8121Smrg      template<typename _U1>
1049fb8a8121Smrg	static constexpr bool __is_alloc_arg()
1050fb8a8121Smrg	{ return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
1051fb8a8121Smrg
10524fee23f9Smrg    public:
1053fb8a8121Smrg      template<bool _Dummy = true,
1054fb8a8121Smrg	       _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
1055fb8a8121Smrg	constexpr
1056fb8a8121Smrg	tuple()
1057fb8a8121Smrg	noexcept(__nothrow_default_constructible())
10584fee23f9Smrg	: _Inherited() { }
10594fee23f9Smrg
1060fb8a8121Smrg      template<bool _Dummy = true,
1061fb8a8121Smrg	       _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
1062fb8a8121Smrg	explicit constexpr
1063fb8a8121Smrg	tuple()
1064fb8a8121Smrg	noexcept(__nothrow_default_constructible())
1065f9a78e0eSmrg	: _Inherited() { }
1066f9a78e0eSmrg
1067fb8a8121Smrg      template<bool _Dummy = true,
1068fb8a8121Smrg	       _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1069fb8a8121Smrg	constexpr
1070fb8a8121Smrg	tuple(const _T1& __a1, const _T2& __a2)
1071fb8a8121Smrg	noexcept(__nothrow_constructible<const _T1&, const _T2&>())
10724fee23f9Smrg	: _Inherited(__a1, __a2) { }
10734fee23f9Smrg
1074fb8a8121Smrg      template<bool _Dummy = true,
1075fb8a8121Smrg	       _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1076fb8a8121Smrg	explicit constexpr
1077fb8a8121Smrg	tuple(const _T1& __a1, const _T2& __a2)
1078fb8a8121Smrg	noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1079f9a78e0eSmrg	: _Inherited(__a1, __a2) { }
1080f9a78e0eSmrg
1081fb8a8121Smrg      template<typename _U1, typename _U2,
1082fb8a8121Smrg	       _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
1083fb8a8121Smrg	constexpr
1084fb8a8121Smrg	tuple(_U1&& __a1, _U2&& __a2)
1085fb8a8121Smrg	noexcept(__nothrow_constructible<_U1, _U2>())
10864fee23f9Smrg	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
10874fee23f9Smrg
1088fb8a8121Smrg      template<typename _U1, typename _U2,
1089fb8a8121Smrg	       _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
1090fb8a8121Smrg	explicit constexpr
1091fb8a8121Smrg	tuple(_U1&& __a1, _U2&& __a2)
1092fb8a8121Smrg	noexcept(__nothrow_constructible<_U1, _U2>())
1093f9a78e0eSmrg	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
1094f9a78e0eSmrg
109548fb7bfaSmrg      constexpr tuple(const tuple&) = default;
10964fee23f9Smrg
109748fb7bfaSmrg      constexpr tuple(tuple&&) = default;
10984fee23f9Smrg
1099fb8a8121Smrg      template<typename _U1, typename _U2,
1100fb8a8121Smrg	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
1101fb8a8121Smrg	constexpr
1102fb8a8121Smrg	tuple(const tuple<_U1, _U2>& __in)
1103fb8a8121Smrg	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
11044fee23f9Smrg	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
11054fee23f9Smrg
1106fb8a8121Smrg      template<typename _U1, typename _U2,
1107fb8a8121Smrg	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
1108fb8a8121Smrg	explicit constexpr
1109fb8a8121Smrg	tuple(const tuple<_U1, _U2>& __in)
1110fb8a8121Smrg	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1111f9a78e0eSmrg	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
1112f9a78e0eSmrg
1113fb8a8121Smrg      template<typename _U1, typename _U2,
1114fb8a8121Smrg	       _ImplicitCtor<true, _U1, _U2> = true>
1115fb8a8121Smrg	constexpr
1116fb8a8121Smrg	tuple(tuple<_U1, _U2>&& __in)
1117fb8a8121Smrg	noexcept(__nothrow_constructible<_U1, _U2>())
11184fee23f9Smrg	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
11194fee23f9Smrg
1120fb8a8121Smrg      template<typename _U1, typename _U2,
1121fb8a8121Smrg	       _ExplicitCtor<true, _U1, _U2> = false>
1122fb8a8121Smrg	explicit constexpr
1123fb8a8121Smrg	tuple(tuple<_U1, _U2>&& __in)
1124fb8a8121Smrg	noexcept(__nothrow_constructible<_U1, _U2>())
1125f9a78e0eSmrg	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
1126f9a78e0eSmrg
1127fb8a8121Smrg      template<typename _U1, typename _U2,
1128fb8a8121Smrg	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
1129fb8a8121Smrg	constexpr
1130fb8a8121Smrg	tuple(const pair<_U1, _U2>& __in)
1131fb8a8121Smrg	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
11324fee23f9Smrg	: _Inherited(__in.first, __in.second) { }
11334fee23f9Smrg
1134fb8a8121Smrg      template<typename _U1, typename _U2,
1135fb8a8121Smrg	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
1136fb8a8121Smrg	explicit constexpr
1137fb8a8121Smrg	tuple(const pair<_U1, _U2>& __in)
1138fb8a8121Smrg	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1139f9a78e0eSmrg	: _Inherited(__in.first, __in.second) { }
1140f9a78e0eSmrg
1141fb8a8121Smrg      template<typename _U1, typename _U2,
1142fb8a8121Smrg	       _ImplicitCtor<true, _U1, _U2> = true>
1143fb8a8121Smrg	constexpr
1144fb8a8121Smrg	tuple(pair<_U1, _U2>&& __in)
1145fb8a8121Smrg	noexcept(__nothrow_constructible<_U1, _U2>())
11464fee23f9Smrg	: _Inherited(std::forward<_U1>(__in.first),
11474fee23f9Smrg		     std::forward<_U2>(__in.second)) { }
11484fee23f9Smrg
1149fb8a8121Smrg      template<typename _U1, typename _U2,
1150fb8a8121Smrg	       _ExplicitCtor<true, _U1, _U2> = false>
1151fb8a8121Smrg	explicit constexpr
1152fb8a8121Smrg	tuple(pair<_U1, _U2>&& __in)
1153fb8a8121Smrg	noexcept(__nothrow_constructible<_U1, _U2>())
1154f9a78e0eSmrg	: _Inherited(std::forward<_U1>(__in.first),
1155f9a78e0eSmrg		     std::forward<_U2>(__in.second)) { }
1156f9a78e0eSmrg
115748fb7bfaSmrg      // Allocator-extended constructors.
115848fb7bfaSmrg
1159fb8a8121Smrg      template<typename _Alloc,
1160fb8a8121Smrg	       _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
1161fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
116248fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a)
116348fb7bfaSmrg	: _Inherited(__tag, __a) { }
116448fb7bfaSmrg
1165*0a307195Smrg      template<typename _Alloc,
1166*0a307195Smrg	       _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
1167*0a307195Smrg	_GLIBCXX20_CONSTEXPR
1168*0a307195Smrg	explicit
1169*0a307195Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a)
1170*0a307195Smrg	: _Inherited(__tag, __a) { }
1171*0a307195Smrg
1172fb8a8121Smrg      template<typename _Alloc, bool _Dummy = true,
1173fb8a8121Smrg	       _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1174fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
117548fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
117648fb7bfaSmrg	      const _T1& __a1, const _T2& __a2)
117748fb7bfaSmrg	: _Inherited(__tag, __a, __a1, __a2) { }
117848fb7bfaSmrg
1179fb8a8121Smrg      template<typename _Alloc, bool _Dummy = true,
1180fb8a8121Smrg	       _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1181fb8a8121Smrg	explicit
1182fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
1183fb8a8121Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
1184f9a78e0eSmrg	      const _T1& __a1, const _T2& __a2)
1185f9a78e0eSmrg	: _Inherited(__tag, __a, __a1, __a2) { }
1186f9a78e0eSmrg
1187fb8a8121Smrg      template<typename _Alloc, typename _U1, typename _U2,
1188fb8a8121Smrg	       _ImplicitCtor<true, _U1, _U2> = true>
1189fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
119048fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
119148fb7bfaSmrg	: _Inherited(__tag, __a, std::forward<_U1>(__a1),
119248fb7bfaSmrg	             std::forward<_U2>(__a2)) { }
119348fb7bfaSmrg
1194fb8a8121Smrg      template<typename _Alloc, typename _U1, typename _U2,
1195fb8a8121Smrg	       _ExplicitCtor<true, _U1, _U2> = false>
1196fb8a8121Smrg	explicit
1197fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
1198fb8a8121Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
1199f9a78e0eSmrg	      _U1&& __a1, _U2&& __a2)
1200f9a78e0eSmrg	: _Inherited(__tag, __a, std::forward<_U1>(__a1),
1201f9a78e0eSmrg	             std::forward<_U2>(__a2)) { }
1202f9a78e0eSmrg
120348fb7bfaSmrg      template<typename _Alloc>
1204fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
120548fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
120648fb7bfaSmrg	: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
120748fb7bfaSmrg
120848fb7bfaSmrg      template<typename _Alloc>
1209fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
121048fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
121148fb7bfaSmrg	: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
121248fb7bfaSmrg
1213fb8a8121Smrg      template<typename _Alloc, typename _U1, typename _U2,
1214fb8a8121Smrg	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
1215fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
121648fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
121748fb7bfaSmrg	      const tuple<_U1, _U2>& __in)
121848fb7bfaSmrg	: _Inherited(__tag, __a,
121948fb7bfaSmrg	             static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
122048fb7bfaSmrg	{ }
122148fb7bfaSmrg
1222fb8a8121Smrg      template<typename _Alloc, typename _U1, typename _U2,
1223fb8a8121Smrg	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
1224fb8a8121Smrg	explicit
1225fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
1226fb8a8121Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
1227f9a78e0eSmrg	      const tuple<_U1, _U2>& __in)
1228f9a78e0eSmrg	: _Inherited(__tag, __a,
1229f9a78e0eSmrg	             static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1230f9a78e0eSmrg	{ }
1231f9a78e0eSmrg
1232fb8a8121Smrg      template<typename _Alloc, typename _U1, typename _U2,
1233fb8a8121Smrg	       _ImplicitCtor<true, _U1, _U2> = true>
1234fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
123548fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
123648fb7bfaSmrg	: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
123748fb7bfaSmrg	{ }
123848fb7bfaSmrg
1239fb8a8121Smrg      template<typename _Alloc, typename _U1, typename _U2,
1240fb8a8121Smrg	       _ExplicitCtor<true, _U1, _U2> = false>
1241fb8a8121Smrg	explicit
1242fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
1243fb8a8121Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
1244f9a78e0eSmrg	: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1245f9a78e0eSmrg	{ }
1246f9a78e0eSmrg
1247fb8a8121Smrg      template<typename _Alloc, typename _U1, typename _U2,
1248fb8a8121Smrg	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
1249fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
125048fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
125148fb7bfaSmrg	      const pair<_U1, _U2>& __in)
125248fb7bfaSmrg	: _Inherited(__tag, __a, __in.first, __in.second) { }
125348fb7bfaSmrg
1254fb8a8121Smrg      template<typename _Alloc, typename _U1, typename _U2,
1255fb8a8121Smrg	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
1256fb8a8121Smrg	explicit
1257fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
1258fb8a8121Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a,
1259f9a78e0eSmrg	      const pair<_U1, _U2>& __in)
1260f9a78e0eSmrg	: _Inherited(__tag, __a, __in.first, __in.second) { }
1261f9a78e0eSmrg
1262fb8a8121Smrg      template<typename _Alloc, typename _U1, typename _U2,
1263fb8a8121Smrg	       _ImplicitCtor<true, _U1, _U2> = true>
1264fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
126548fb7bfaSmrg	tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
126648fb7bfaSmrg	: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
126748fb7bfaSmrg		     std::forward<_U2>(__in.second)) { }
126848fb7bfaSmrg
1269fb8a8121Smrg      template<typename _Alloc, typename _U1, typename _U2,
1270fb8a8121Smrg	       _ExplicitCtor<true, _U1, _U2> = false>
1271fb8a8121Smrg	explicit
1272fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
1273fb8a8121Smrg	tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
1274f9a78e0eSmrg	: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
1275f9a78e0eSmrg		     std::forward<_U2>(__in.second)) { }
1276f9a78e0eSmrg
1277fb8a8121Smrg      // Tuple assignment.
1278fb8a8121Smrg
1279fb8a8121Smrg      _GLIBCXX20_CONSTEXPR
12804fee23f9Smrg      tuple&
1281b1e83836Smrg      operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
1282181254a7Smrg				const tuple&,
1283b1e83836Smrg				const __nonesuch&> __in)
1284181254a7Smrg      noexcept(__nothrow_assignable<const _T1&, const _T2&>())
12854fee23f9Smrg      {
1286181254a7Smrg	this->_M_assign(__in);
12874fee23f9Smrg	return *this;
12884fee23f9Smrg      }
12894fee23f9Smrg
1290fb8a8121Smrg      _GLIBCXX20_CONSTEXPR
12914fee23f9Smrg      tuple&
1292b1e83836Smrg      operator=(__conditional_t<__assignable<_T1, _T2>(),
1293181254a7Smrg				tuple&&,
1294b1e83836Smrg				__nonesuch&&> __in)
1295181254a7Smrg      noexcept(__nothrow_assignable<_T1, _T2>())
12964fee23f9Smrg      {
1297181254a7Smrg	this->_M_assign(std::move(__in));
12984fee23f9Smrg	return *this;
12994fee23f9Smrg      }
13004fee23f9Smrg
13014fee23f9Smrg      template<typename _U1, typename _U2>
1302fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
1303181254a7Smrg	__enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
13044fee23f9Smrg	operator=(const tuple<_U1, _U2>& __in)
1305181254a7Smrg	noexcept(__nothrow_assignable<const _U1&, const _U2&>())
13064fee23f9Smrg	{
1307181254a7Smrg	  this->_M_assign(__in);
13084fee23f9Smrg	  return *this;
13094fee23f9Smrg	}
13104fee23f9Smrg
13114fee23f9Smrg      template<typename _U1, typename _U2>
1312fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
1313181254a7Smrg	__enable_if_t<__assignable<_U1, _U2>(), tuple&>
13144fee23f9Smrg	operator=(tuple<_U1, _U2>&& __in)
1315181254a7Smrg	noexcept(__nothrow_assignable<_U1, _U2>())
13164fee23f9Smrg	{
1317181254a7Smrg	  this->_M_assign(std::move(__in));
13184fee23f9Smrg	  return *this;
13194fee23f9Smrg	}
13204fee23f9Smrg
13214fee23f9Smrg      template<typename _U1, typename _U2>
1322fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
1323181254a7Smrg	__enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
13244fee23f9Smrg	operator=(const pair<_U1, _U2>& __in)
1325181254a7Smrg	noexcept(__nothrow_assignable<const _U1&, const _U2&>())
13264fee23f9Smrg	{
132748fb7bfaSmrg	  this->_M_head(*this) = __in.first;
132848fb7bfaSmrg	  this->_M_tail(*this)._M_head(*this) = __in.second;
13294fee23f9Smrg	  return *this;
13304fee23f9Smrg	}
13314fee23f9Smrg
13324fee23f9Smrg      template<typename _U1, typename _U2>
1333fb8a8121Smrg	_GLIBCXX20_CONSTEXPR
1334181254a7Smrg	__enable_if_t<__assignable<_U1, _U2>(), tuple&>
13354fee23f9Smrg	operator=(pair<_U1, _U2>&& __in)
1336181254a7Smrg	noexcept(__nothrow_assignable<_U1, _U2>())
13374fee23f9Smrg	{
133848fb7bfaSmrg	  this->_M_head(*this) = std::forward<_U1>(__in.first);
133948fb7bfaSmrg	  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
13404fee23f9Smrg	  return *this;
13414fee23f9Smrg	}
13424fee23f9Smrg
1343fb8a8121Smrg      _GLIBCXX20_CONSTEXPR
13444fee23f9Smrg      void
13454fee23f9Smrg      swap(tuple& __in)
1346181254a7Smrg      noexcept(__and_<__is_nothrow_swappable<_T1>,
1347181254a7Smrg		      __is_nothrow_swappable<_T2>>::value)
134848fb7bfaSmrg      { _Inherited::_M_swap(__in); }
13494fee23f9Smrg    };
13504fee23f9Smrg
13514fee23f9Smrg
1352b17d1066Smrg  /// class tuple_size
1353b17d1066Smrg  template<typename... _Elements>
1354b17d1066Smrg    struct tuple_size<tuple<_Elements...>>
1355b1e83836Smrg    : public integral_constant<size_t, sizeof...(_Elements)> { };
1356b17d1066Smrg
1357b1e83836Smrg#if __cplusplus >= 201703L
1358b1e83836Smrg  template<typename... _Types>
1359b1e83836Smrg    inline constexpr size_t tuple_size_v<tuple<_Types...>>
1360b1e83836Smrg      = sizeof...(_Types);
1361b1e83836Smrg
1362b1e83836Smrg  template<typename... _Types>
1363b1e83836Smrg    inline constexpr size_t tuple_size_v<const tuple<_Types...>>
1364b1e83836Smrg      = sizeof...(_Types);
1365b17d1066Smrg#endif
1366b17d1066Smrg
1367b1e83836Smrg  /// Trait to get the Ith element type from a tuple.
1368b1e83836Smrg  template<size_t __i, typename... _Types>
1369b1e83836Smrg    struct tuple_element<__i, tuple<_Types...>>
13704fee23f9Smrg    {
1371b1e83836Smrg      static_assert(__i < sizeof...(_Types), "tuple index must be in range");
1372b1e83836Smrg
1373b1e83836Smrg      using type = typename _Nth_type<__i, _Types...>::type;
13744fee23f9Smrg    };
13754fee23f9Smrg
1376b1e83836Smrg  template<size_t __i, typename _Head, typename... _Tail>
13774d5abbe8Smrg    constexpr _Head&
137848fb7bfaSmrg    __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
137948fb7bfaSmrg    { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
13804fee23f9Smrg
1381b1e83836Smrg  template<size_t __i, typename _Head, typename... _Tail>
13824d5abbe8Smrg    constexpr const _Head&
138348fb7bfaSmrg    __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
138448fb7bfaSmrg    { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
13854fee23f9Smrg
1386b1e83836Smrg  // Deleted overload to improve diagnostics for invalid indices
1387b1e83836Smrg  template<size_t __i, typename... _Types>
1388b1e83836Smrg    __enable_if_t<(__i >= sizeof...(_Types))>
1389b1e83836Smrg    __get_helper(const tuple<_Types...>&) = delete;
1390b1e83836Smrg
13914d5abbe8Smrg  /// Return a reference to the ith element of a tuple.
1392b1e83836Smrg  template<size_t __i, typename... _Elements>
13934d5abbe8Smrg    constexpr __tuple_element_t<__i, tuple<_Elements...>>&
139448fb7bfaSmrg    get(tuple<_Elements...>& __t) noexcept
13955f4cdc7dSskrll    { return std::__get_helper<__i>(__t); }
13964fee23f9Smrg
13974d5abbe8Smrg  /// Return a const reference to the ith element of a const tuple.
1398b1e83836Smrg  template<size_t __i, typename... _Elements>
13994d5abbe8Smrg    constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
140048fb7bfaSmrg    get(const tuple<_Elements...>& __t) noexcept
14015f4cdc7dSskrll    { return std::__get_helper<__i>(__t); }
14024fee23f9Smrg
14034d5abbe8Smrg  /// Return an rvalue reference to the ith element of a tuple rvalue.
1404b1e83836Smrg  template<size_t __i, typename... _Elements>
14054d5abbe8Smrg    constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
140648fb7bfaSmrg    get(tuple<_Elements...>&& __t) noexcept
14074d5abbe8Smrg    {
14084d5abbe8Smrg      typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
1409b1e83836Smrg      return std::forward<__element_type>(std::__get_helper<__i>(__t));
14104d5abbe8Smrg    }
141148fb7bfaSmrg
1412a3e9eb18Smrg  /// Return a const rvalue reference to the ith element of a const tuple rvalue.
1413b1e83836Smrg  template<size_t __i, typename... _Elements>
1414a3e9eb18Smrg    constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
1415a3e9eb18Smrg    get(const tuple<_Elements...>&& __t) noexcept
1416a3e9eb18Smrg    {
1417a3e9eb18Smrg      typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
1418b1e83836Smrg      return std::forward<const __element_type>(std::__get_helper<__i>(__t));
1419a3e9eb18Smrg    }
1420a3e9eb18Smrg
1421b1e83836Smrg  /// @cond undocumented
1422b1e83836Smrg  // Deleted overload chosen for invalid indices.
1423b1e83836Smrg  template<size_t __i, typename... _Elements>
1424b1e83836Smrg    constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
1425b1e83836Smrg    get(const tuple<_Elements...>&) = delete;
1426b1e83836Smrg  /// @endcond
1427b1e83836Smrg
1428181254a7Smrg#if __cplusplus >= 201402L
14294fee23f9Smrg
1430b1e83836Smrg#define __cpp_lib_tuples_by_type 201304L
14314d5abbe8Smrg
14324d5abbe8Smrg  /// Return a reference to the unique element of type _Tp of a tuple.
14334d5abbe8Smrg  template <typename _Tp, typename... _Types>
14344d5abbe8Smrg    constexpr _Tp&
14354d5abbe8Smrg    get(tuple<_Types...>& __t) noexcept
1436b1e83836Smrg    {
1437b1e83836Smrg      constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1438b1e83836Smrg      static_assert(__idx < sizeof...(_Types),
1439b1e83836Smrg	  "the type T in std::get<T> must occur exactly once in the tuple");
1440b1e83836Smrg      return std::__get_helper<__idx>(__t);
1441b1e83836Smrg    }
14424d5abbe8Smrg
14434d5abbe8Smrg  /// Return a reference to the unique element of type _Tp of a tuple rvalue.
14444d5abbe8Smrg  template <typename _Tp, typename... _Types>
14454d5abbe8Smrg    constexpr _Tp&&
14464d5abbe8Smrg    get(tuple<_Types...>&& __t) noexcept
1447b1e83836Smrg    {
1448b1e83836Smrg      constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1449b1e83836Smrg      static_assert(__idx < sizeof...(_Types),
1450b1e83836Smrg	  "the type T in std::get<T> must occur exactly once in the tuple");
1451b1e83836Smrg      return std::forward<_Tp>(std::__get_helper<__idx>(__t));
1452b1e83836Smrg    }
14534d5abbe8Smrg
14544d5abbe8Smrg  /// Return a const reference to the unique element of type _Tp of a tuple.
14554d5abbe8Smrg  template <typename _Tp, typename... _Types>
14564d5abbe8Smrg    constexpr const _Tp&
14574d5abbe8Smrg    get(const tuple<_Types...>& __t) noexcept
1458b1e83836Smrg    {
1459b1e83836Smrg      constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1460b1e83836Smrg      static_assert(__idx < sizeof...(_Types),
1461b1e83836Smrg	  "the type T in std::get<T> must occur exactly once in the tuple");
1462b1e83836Smrg      return std::__get_helper<__idx>(__t);
1463b1e83836Smrg    }
1464a3e9eb18Smrg
1465a3e9eb18Smrg  /// Return a const reference to the unique element of type _Tp of
1466a3e9eb18Smrg  /// a const tuple rvalue.
1467a3e9eb18Smrg  template <typename _Tp, typename... _Types>
1468a3e9eb18Smrg    constexpr const _Tp&&
1469a3e9eb18Smrg    get(const tuple<_Types...>&& __t) noexcept
1470b1e83836Smrg    {
1471b1e83836Smrg      constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1472b1e83836Smrg      static_assert(__idx < sizeof...(_Types),
1473b1e83836Smrg	  "the type T in std::get<T> must occur exactly once in the tuple");
1474b1e83836Smrg      return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
1475b1e83836Smrg    }
14764d5abbe8Smrg#endif
14774d5abbe8Smrg
14784d5abbe8Smrg  // This class performs the comparison operations on tuples
14794d5abbe8Smrg  template<typename _Tp, typename _Up, size_t __i, size_t __size>
14804d5abbe8Smrg    struct __tuple_compare
14814fee23f9Smrg    {
148248fb7bfaSmrg      static constexpr bool
148348fb7bfaSmrg      __eq(const _Tp& __t, const _Up& __u)
14844fee23f9Smrg      {
14854d5abbe8Smrg	return bool(std::get<__i>(__t) == std::get<__i>(__u))
14864d5abbe8Smrg	  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
14874fee23f9Smrg      }
14884fee23f9Smrg
148948fb7bfaSmrg      static constexpr bool
149048fb7bfaSmrg      __less(const _Tp& __t, const _Up& __u)
14914fee23f9Smrg      {
14924d5abbe8Smrg	return bool(std::get<__i>(__t) < std::get<__i>(__u))
14934d5abbe8Smrg	  || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
14944d5abbe8Smrg	      && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
14954fee23f9Smrg      }
14964fee23f9Smrg    };
14974fee23f9Smrg
14984d5abbe8Smrg  template<typename _Tp, typename _Up, size_t __size>
14994d5abbe8Smrg    struct __tuple_compare<_Tp, _Up, __size, __size>
15004fee23f9Smrg    {
150148fb7bfaSmrg      static constexpr bool
150248fb7bfaSmrg      __eq(const _Tp&, const _Up&) { return true; }
15034fee23f9Smrg
150448fb7bfaSmrg      static constexpr bool
150548fb7bfaSmrg      __less(const _Tp&, const _Up&) { return false; }
15064fee23f9Smrg    };
15074fee23f9Smrg
15084fee23f9Smrg  template<typename... _TElements, typename... _UElements>
150948fb7bfaSmrg    constexpr bool
15104fee23f9Smrg    operator==(const tuple<_TElements...>& __t,
15114fee23f9Smrg	       const tuple<_UElements...>& __u)
15124fee23f9Smrg    {
15134d5abbe8Smrg      static_assert(sizeof...(_TElements) == sizeof...(_UElements),
15144d5abbe8Smrg	  "tuple objects can only be compared if they have equal sizes.");
15154d5abbe8Smrg      using __compare = __tuple_compare<tuple<_TElements...>,
15164d5abbe8Smrg					tuple<_UElements...>,
15174d5abbe8Smrg					0, sizeof...(_TElements)>;
15184d5abbe8Smrg      return __compare::__eq(__t, __u);
15194fee23f9Smrg    }
15204fee23f9Smrg
1521fb8a8121Smrg#if __cpp_lib_three_way_comparison
1522fb8a8121Smrg  template<typename _Cat, typename _Tp, typename _Up>
1523fb8a8121Smrg    constexpr _Cat
1524fb8a8121Smrg    __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
1525fb8a8121Smrg    { return _Cat::equivalent; }
1526fb8a8121Smrg
1527fb8a8121Smrg  template<typename _Cat, typename _Tp, typename _Up,
1528fb8a8121Smrg	   size_t _Idx0, size_t... _Idxs>
1529fb8a8121Smrg    constexpr _Cat
1530fb8a8121Smrg    __tuple_cmp(const _Tp& __t, const _Up& __u,
1531fb8a8121Smrg		index_sequence<_Idx0, _Idxs...>)
1532fb8a8121Smrg    {
1533fb8a8121Smrg      auto __c
1534fb8a8121Smrg	= __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
1535fb8a8121Smrg      if (__c != 0)
1536fb8a8121Smrg	return __c;
1537fb8a8121Smrg      return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
1538fb8a8121Smrg    }
1539fb8a8121Smrg
1540fb8a8121Smrg  template<typename... _Tps, typename... _Ups>
1541fb8a8121Smrg    constexpr
1542fb8a8121Smrg    common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
1543fb8a8121Smrg    operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
1544fb8a8121Smrg    {
1545fb8a8121Smrg      using _Cat
1546fb8a8121Smrg	= common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
1547fb8a8121Smrg      return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
1548fb8a8121Smrg    }
1549fb8a8121Smrg#else
15504fee23f9Smrg  template<typename... _TElements, typename... _UElements>
155148fb7bfaSmrg    constexpr bool
15524fee23f9Smrg    operator<(const tuple<_TElements...>& __t,
15534fee23f9Smrg	      const tuple<_UElements...>& __u)
15544fee23f9Smrg    {
15554d5abbe8Smrg      static_assert(sizeof...(_TElements) == sizeof...(_UElements),
15564d5abbe8Smrg	  "tuple objects can only be compared if they have equal sizes.");
15574d5abbe8Smrg      using __compare = __tuple_compare<tuple<_TElements...>,
15584d5abbe8Smrg					tuple<_UElements...>,
15594d5abbe8Smrg					0, sizeof...(_TElements)>;
15604d5abbe8Smrg      return __compare::__less(__t, __u);
15614fee23f9Smrg    }
15624fee23f9Smrg
15634fee23f9Smrg  template<typename... _TElements, typename... _UElements>
15644d5abbe8Smrg    constexpr bool
15654fee23f9Smrg    operator!=(const tuple<_TElements...>& __t,
15664fee23f9Smrg	       const tuple<_UElements...>& __u)
15674fee23f9Smrg    { return !(__t == __u); }
15684fee23f9Smrg
15694fee23f9Smrg  template<typename... _TElements, typename... _UElements>
15704d5abbe8Smrg    constexpr bool
15714fee23f9Smrg    operator>(const tuple<_TElements...>& __t,
15724fee23f9Smrg	      const tuple<_UElements...>& __u)
15734fee23f9Smrg    { return __u < __t; }
15744fee23f9Smrg
15754fee23f9Smrg  template<typename... _TElements, typename... _UElements>
15764d5abbe8Smrg    constexpr bool
15774fee23f9Smrg    operator<=(const tuple<_TElements...>& __t,
15784fee23f9Smrg	       const tuple<_UElements...>& __u)
15794fee23f9Smrg    { return !(__u < __t); }
15804fee23f9Smrg
15814fee23f9Smrg  template<typename... _TElements, typename... _UElements>
15824d5abbe8Smrg    constexpr bool
15834fee23f9Smrg    operator>=(const tuple<_TElements...>& __t,
15844fee23f9Smrg	       const tuple<_UElements...>& __u)
15854fee23f9Smrg    { return !(__t < __u); }
1586fb8a8121Smrg#endif // three_way_comparison
15874fee23f9Smrg
15884fee23f9Smrg  // NB: DR 705.
1589*0a307195Smrg  /// Create a tuple containing copies of the arguments
15904fee23f9Smrg  template<typename... _Elements>
159148fb7bfaSmrg    constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
15924fee23f9Smrg    make_tuple(_Elements&&... __args)
15934fee23f9Smrg    {
15944fee23f9Smrg      typedef tuple<typename __decay_and_strip<_Elements>::__type...>
15954fee23f9Smrg	__result_type;
15964fee23f9Smrg      return __result_type(std::forward<_Elements>(__args)...);
15974fee23f9Smrg    }
15984fee23f9Smrg
1599f9a78e0eSmrg  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1600f9a78e0eSmrg  // 2275. Why is forward_as_tuple not constexpr?
1601*0a307195Smrg  /// Create a tuple of lvalue or rvalue references to the arguments
160248fb7bfaSmrg  template<typename... _Elements>
1603f9a78e0eSmrg    constexpr tuple<_Elements&&...>
160448fb7bfaSmrg    forward_as_tuple(_Elements&&... __args) noexcept
160548fb7bfaSmrg    { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
16064fee23f9Smrg
1607b1e83836Smrg  // Declarations of std::array and its std::get overloads, so that
1608b1e83836Smrg  // std::tuple_cat can use them if <tuple> is included before <array>.
1609b1e83836Smrg
1610b1e83836Smrg  template<typename _Tp, size_t _Nm> struct array;
1611b1e83836Smrg
1612b1e83836Smrg  template<size_t _Int, typename _Tp, size_t _Nm>
1613b1e83836Smrg    constexpr _Tp&
1614b1e83836Smrg    get(array<_Tp, _Nm>&) noexcept;
1615b1e83836Smrg
1616b1e83836Smrg  template<size_t _Int, typename _Tp, size_t _Nm>
1617b1e83836Smrg    constexpr _Tp&&
1618b1e83836Smrg    get(array<_Tp, _Nm>&&) noexcept;
1619b1e83836Smrg
1620b1e83836Smrg  template<size_t _Int, typename _Tp, size_t _Nm>
1621b1e83836Smrg    constexpr const _Tp&
1622b1e83836Smrg    get(const array<_Tp, _Nm>&) noexcept;
1623b1e83836Smrg
1624b1e83836Smrg  template<size_t _Int, typename _Tp, size_t _Nm>
1625b1e83836Smrg    constexpr const _Tp&&
1626b1e83836Smrg    get(const array<_Tp, _Nm>&&) noexcept;
1627b1e83836Smrg
1628*0a307195Smrg  /// @cond undocumented
16294d5abbe8Smrg  template<size_t, typename, typename, size_t>
163048fb7bfaSmrg    struct __make_tuple_impl;
163148fb7bfaSmrg
16324d5abbe8Smrg  template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
163348fb7bfaSmrg    struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
16344d5abbe8Smrg    : __make_tuple_impl<_Idx + 1,
16354d5abbe8Smrg			tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
16364d5abbe8Smrg			_Tuple, _Nm>
16374d5abbe8Smrg    { };
163848fb7bfaSmrg
1639b1e83836Smrg  template<size_t _Nm, typename _Tuple, typename... _Tp>
164048fb7bfaSmrg    struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
164148fb7bfaSmrg    {
164248fb7bfaSmrg      typedef tuple<_Tp...> __type;
164348fb7bfaSmrg    };
164448fb7bfaSmrg
164548fb7bfaSmrg  template<typename _Tuple>
164648fb7bfaSmrg    struct __do_make_tuple
1647b1e83836Smrg    : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
164848fb7bfaSmrg    { };
164948fb7bfaSmrg
165048fb7bfaSmrg  // Returns the std::tuple equivalent of a tuple-like type.
165148fb7bfaSmrg  template<typename _Tuple>
165248fb7bfaSmrg    struct __make_tuple
1653181254a7Smrg    : public __do_make_tuple<__remove_cvref_t<_Tuple>>
165448fb7bfaSmrg    { };
165548fb7bfaSmrg
165648fb7bfaSmrg  // Combines several std::tuple's into a single one.
165748fb7bfaSmrg  template<typename...>
165848fb7bfaSmrg    struct __combine_tuples;
165948fb7bfaSmrg
166048fb7bfaSmrg  template<>
166148fb7bfaSmrg    struct __combine_tuples<>
166248fb7bfaSmrg    {
166348fb7bfaSmrg      typedef tuple<> __type;
166448fb7bfaSmrg    };
166548fb7bfaSmrg
166648fb7bfaSmrg  template<typename... _Ts>
166748fb7bfaSmrg    struct __combine_tuples<tuple<_Ts...>>
166848fb7bfaSmrg    {
166948fb7bfaSmrg      typedef tuple<_Ts...> __type;
167048fb7bfaSmrg    };
167148fb7bfaSmrg
167248fb7bfaSmrg  template<typename... _T1s, typename... _T2s, typename... _Rem>
167348fb7bfaSmrg    struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
167448fb7bfaSmrg    {
167548fb7bfaSmrg      typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
167648fb7bfaSmrg					_Rem...>::__type __type;
167748fb7bfaSmrg    };
167848fb7bfaSmrg
167948fb7bfaSmrg  // Computes the result type of tuple_cat given a set of tuple-like types.
168048fb7bfaSmrg  template<typename... _Tpls>
168148fb7bfaSmrg    struct __tuple_cat_result
168248fb7bfaSmrg    {
168348fb7bfaSmrg      typedef typename __combine_tuples
168448fb7bfaSmrg        <typename __make_tuple<_Tpls>::__type...>::__type __type;
168548fb7bfaSmrg    };
168648fb7bfaSmrg
168748fb7bfaSmrg  // Helper to determine the index set for the first tuple-like
168848fb7bfaSmrg  // type of a given set.
168948fb7bfaSmrg  template<typename...>
169048fb7bfaSmrg    struct __make_1st_indices;
169148fb7bfaSmrg
169248fb7bfaSmrg  template<>
169348fb7bfaSmrg    struct __make_1st_indices<>
169448fb7bfaSmrg    {
1695b1e83836Smrg      typedef _Index_tuple<> __type;
169648fb7bfaSmrg    };
169748fb7bfaSmrg
169848fb7bfaSmrg  template<typename _Tp, typename... _Tpls>
169948fb7bfaSmrg    struct __make_1st_indices<_Tp, _Tpls...>
170048fb7bfaSmrg    {
1701b1e83836Smrg      typedef typename _Build_index_tuple<tuple_size<
1702b1e83836Smrg	typename remove_reference<_Tp>::type>::value>::__type __type;
170348fb7bfaSmrg    };
170448fb7bfaSmrg
170548fb7bfaSmrg  // Performs the actual concatenation by step-wise expanding tuple-like
170648fb7bfaSmrg  // objects into the elements,  which are finally forwarded into the
170748fb7bfaSmrg  // result tuple.
170848fb7bfaSmrg  template<typename _Ret, typename _Indices, typename... _Tpls>
170948fb7bfaSmrg    struct __tuple_concater;
171048fb7bfaSmrg
1711b1e83836Smrg  template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
1712b1e83836Smrg    struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
171348fb7bfaSmrg    {
171448fb7bfaSmrg      template<typename... _Us>
171548fb7bfaSmrg        static constexpr _Ret
171648fb7bfaSmrg        _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
171748fb7bfaSmrg        {
171848fb7bfaSmrg	  typedef typename __make_1st_indices<_Tpls...>::__type __idx;
171948fb7bfaSmrg	  typedef __tuple_concater<_Ret, __idx, _Tpls...>      __next;
172048fb7bfaSmrg	  return __next::_S_do(std::forward<_Tpls>(__tps)...,
172148fb7bfaSmrg			       std::forward<_Us>(__us)...,
172248fb7bfaSmrg			       std::get<_Is>(std::forward<_Tp>(__tp))...);
172348fb7bfaSmrg	}
172448fb7bfaSmrg    };
172548fb7bfaSmrg
172648fb7bfaSmrg  template<typename _Ret>
1727b1e83836Smrg    struct __tuple_concater<_Ret, _Index_tuple<>>
172848fb7bfaSmrg    {
172948fb7bfaSmrg      template<typename... _Us>
173048fb7bfaSmrg	static constexpr _Ret
173148fb7bfaSmrg	_S_do(_Us&&... __us)
173248fb7bfaSmrg        {
173348fb7bfaSmrg	  return _Ret(std::forward<_Us>(__us)...);
173448fb7bfaSmrg	}
173548fb7bfaSmrg    };
173648fb7bfaSmrg
1737b1e83836Smrg  template<typename... _Tps>
1738b1e83836Smrg    struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
1739b1e83836Smrg    { };
1740*0a307195Smrg  /// @endcond
1741b1e83836Smrg
1742*0a307195Smrg  /// Create a `tuple` containing all elements from multiple tuple-like objects
174348fb7bfaSmrg  template<typename... _Tpls, typename = typename
174448fb7bfaSmrg           enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
174548fb7bfaSmrg    constexpr auto
174648fb7bfaSmrg    tuple_cat(_Tpls&&... __tpls)
174748fb7bfaSmrg    -> typename __tuple_cat_result<_Tpls...>::__type
174848fb7bfaSmrg    {
174948fb7bfaSmrg      typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
175048fb7bfaSmrg      typedef typename __make_1st_indices<_Tpls...>::__type __idx;
175148fb7bfaSmrg      typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
175248fb7bfaSmrg      return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
17534fee23f9Smrg    }
17544fee23f9Smrg
1755f9a78e0eSmrg  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1756f9a78e0eSmrg  // 2301. Why is tie not constexpr?
1757*0a307195Smrg  /// Return a tuple of lvalue references bound to the arguments
17584fee23f9Smrg  template<typename... _Elements>
1759f9a78e0eSmrg    constexpr tuple<_Elements&...>
176048fb7bfaSmrg    tie(_Elements&... __args) noexcept
17614fee23f9Smrg    { return tuple<_Elements&...>(__args...); }
17624fee23f9Smrg
1763*0a307195Smrg  /// Exchange the values of two tuples
17644fee23f9Smrg  template<typename... _Elements>
1765fb8a8121Smrg    _GLIBCXX20_CONSTEXPR
1766b17d1066Smrg    inline
1767b17d1066Smrg#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
1768b17d1066Smrg    // Constrained free swap overload, see p0185r1
1769b17d1066Smrg    typename enable_if<__and_<__is_swappable<_Elements>...>::value
1770b17d1066Smrg      >::type
1771b17d1066Smrg#else
1772b17d1066Smrg    void
1773b17d1066Smrg#endif
17744fee23f9Smrg    swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
177548fb7bfaSmrg    noexcept(noexcept(__x.swap(__y)))
17764fee23f9Smrg    { __x.swap(__y); }
17774fee23f9Smrg
1778b17d1066Smrg#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
1779*0a307195Smrg  /// Exchange the values of two const tuples (if const elements can be swapped)
1780b17d1066Smrg  template<typename... _Elements>
1781fb8a8121Smrg    _GLIBCXX20_CONSTEXPR
1782b17d1066Smrg    typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
1783b17d1066Smrg    swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
1784b17d1066Smrg#endif
1785b17d1066Smrg
17864fee23f9Smrg  // A class (and instance) which can be used in 'tie' when an element
1787b17d1066Smrg  // of a tuple is not required.
1788b17d1066Smrg  // _GLIBCXX14_CONSTEXPR
1789b17d1066Smrg  // 2933. PR for LWG 2773 could be clearer
17904fee23f9Smrg  struct _Swallow_assign
17914fee23f9Smrg  {
17924fee23f9Smrg    template<class _Tp>
1793b17d1066Smrg      _GLIBCXX14_CONSTEXPR const _Swallow_assign&
179448fb7bfaSmrg      operator=(const _Tp&) const
17954fee23f9Smrg      { return *this; }
17964fee23f9Smrg  };
17974fee23f9Smrg
1798b17d1066Smrg  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1799b17d1066Smrg  // 2773. Making std::ignore constexpr
1800*0a307195Smrg  /** Used with `std::tie` to ignore an element of a tuple
1801*0a307195Smrg   *
1802*0a307195Smrg   * When using `std::tie` to assign the elements of a tuple to variables,
1803*0a307195Smrg   * unwanted elements can be ignored by using `std::ignore`. For example:
1804*0a307195Smrg   *
1805*0a307195Smrg   * ```
1806*0a307195Smrg   * int x, y;
1807*0a307195Smrg   * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
1808*0a307195Smrg   * ```
1809*0a307195Smrg   *
1810*0a307195Smrg   * This assignment will perform `x=1; std::ignore=2; y=3;` which results
1811*0a307195Smrg   * in the second element being ignored.
1812*0a307195Smrg   *
1813*0a307195Smrg   * @since C++11
1814*0a307195Smrg   */
1815b17d1066Smrg  _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
18164fee23f9Smrg
181748fb7bfaSmrg  /// Partial specialization for tuples
181848fb7bfaSmrg  template<typename... _Types, typename _Alloc>
181948fb7bfaSmrg    struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
182048fb7bfaSmrg
182148fb7bfaSmrg  // See stl_pair.h...
1822fb8a8121Smrg  /** "piecewise construction" using a tuple of arguments for each member.
1823fb8a8121Smrg   *
1824fb8a8121Smrg   * @param __first Arguments for the first member of the pair.
1825fb8a8121Smrg   * @param __second Arguments for the second member of the pair.
1826fb8a8121Smrg   *
1827fb8a8121Smrg   * The elements of each tuple will be used as the constructor arguments
1828fb8a8121Smrg   * for the data members of the pair.
1829fb8a8121Smrg  */
183048fb7bfaSmrg  template<class _T1, class _T2>
183148fb7bfaSmrg    template<typename... _Args1, typename... _Args2>
1832fb8a8121Smrg      _GLIBCXX20_CONSTEXPR
183348fb7bfaSmrg      inline
183448fb7bfaSmrg      pair<_T1, _T2>::
183548fb7bfaSmrg      pair(piecewise_construct_t,
183648fb7bfaSmrg	   tuple<_Args1...> __first, tuple<_Args2...> __second)
183748fb7bfaSmrg      : pair(__first, __second,
183848fb7bfaSmrg	     typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
183948fb7bfaSmrg	     typename _Build_index_tuple<sizeof...(_Args2)>::__type())
184048fb7bfaSmrg      { }
184148fb7bfaSmrg
184248fb7bfaSmrg  template<class _T1, class _T2>
1843b1e83836Smrg    template<typename... _Args1, size_t... _Indexes1,
1844b1e83836Smrg	     typename... _Args2, size_t... _Indexes2>
1845fb8a8121Smrg      _GLIBCXX20_CONSTEXPR inline
184648fb7bfaSmrg      pair<_T1, _T2>::
184748fb7bfaSmrg      pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
184848fb7bfaSmrg	   _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
184948fb7bfaSmrg      : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
185048fb7bfaSmrg	second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
185148fb7bfaSmrg      { }
185248fb7bfaSmrg
1853181254a7Smrg#if __cplusplus >= 201703L
1854fb8a8121Smrg
1855fb8a8121Smrg  // Unpack a std::tuple into a type trait and use its value.
1856fb8a8121Smrg  // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
1857fb8a8121Smrg  // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
1858fb8a8121Smrg  // Otherwise the result is false (because we don't know if std::get throws).
1859fb8a8121Smrg  template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
1860fb8a8121Smrg    inline constexpr bool __unpack_std_tuple = false;
1861fb8a8121Smrg
1862fb8a8121Smrg  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
1863fb8a8121Smrg    inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
1864fb8a8121Smrg      = _Trait<_Tp, _Up...>::value;
1865fb8a8121Smrg
1866fb8a8121Smrg  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
1867fb8a8121Smrg    inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
1868fb8a8121Smrg      = _Trait<_Tp, _Up&...>::value;
1869fb8a8121Smrg
1870fb8a8121Smrg  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
1871fb8a8121Smrg    inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
1872fb8a8121Smrg      = _Trait<_Tp, const _Up...>::value;
1873fb8a8121Smrg
1874fb8a8121Smrg  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
1875fb8a8121Smrg    inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
1876fb8a8121Smrg      = _Trait<_Tp, const _Up&...>::value;
1877fb8a8121Smrg
1878b1e83836Smrg# define __cpp_lib_apply 201603L
1879b17d1066Smrg
1880b17d1066Smrg  template <typename _Fn, typename _Tuple, size_t... _Idx>
1881b17d1066Smrg    constexpr decltype(auto)
1882b17d1066Smrg    __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
1883b17d1066Smrg    {
1884b17d1066Smrg      return std::__invoke(std::forward<_Fn>(__f),
1885b17d1066Smrg			   std::get<_Idx>(std::forward<_Tuple>(__t))...);
1886b17d1066Smrg    }
1887b17d1066Smrg
1888b17d1066Smrg  template <typename _Fn, typename _Tuple>
1889b17d1066Smrg    constexpr decltype(auto)
1890b17d1066Smrg    apply(_Fn&& __f, _Tuple&& __t)
1891fb8a8121Smrg    noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
1892b17d1066Smrg    {
1893181254a7Smrg      using _Indices
1894181254a7Smrg	= make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
1895b17d1066Smrg      return std::__apply_impl(std::forward<_Fn>(__f),
1896b17d1066Smrg			       std::forward<_Tuple>(__t),
1897b17d1066Smrg			       _Indices{});
1898b17d1066Smrg    }
1899b17d1066Smrg
1900b1e83836Smrg#define __cpp_lib_make_from_tuple  201606L
1901b17d1066Smrg
1902b17d1066Smrg  template <typename _Tp, typename _Tuple, size_t... _Idx>
1903b17d1066Smrg    constexpr _Tp
1904b17d1066Smrg    __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
1905b17d1066Smrg    { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
1906b17d1066Smrg
1907b17d1066Smrg  template <typename _Tp, typename _Tuple>
1908b17d1066Smrg    constexpr _Tp
1909b17d1066Smrg    make_from_tuple(_Tuple&& __t)
1910fb8a8121Smrg    noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
1911b17d1066Smrg    {
1912b17d1066Smrg      return __make_from_tuple_impl<_Tp>(
1913b17d1066Smrg        std::forward<_Tuple>(__t),
1914181254a7Smrg	make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>{});
1915b17d1066Smrg    }
1916b17d1066Smrg#endif // C++17
1917b17d1066Smrg
191848fb7bfaSmrg  /// @}
191948fb7bfaSmrg
192048fb7bfaSmrg_GLIBCXX_END_NAMESPACE_VERSION
192148fb7bfaSmrg} // namespace std
192248fb7bfaSmrg
192348fb7bfaSmrg#endif // C++11
19244fee23f9Smrg
19254fee23f9Smrg#endif // _GLIBCXX_TUPLE
1926