Home | History | Annotate | Line # | Download | only in std
      1 // <tuple> -*- C++ -*-
      2 
      3 // Copyright (C) 2007-2024 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file include/tuple
     26  *  This is a Standard C++ Library header.
     27  */
     28 
     29 #ifndef _GLIBCXX_TUPLE
     30 #define _GLIBCXX_TUPLE 1
     31 
     32 #pragma GCC system_header
     33 
     34 #if __cplusplus < 201103L
     35 # include <bits/c++0x_warning.h>
     36 #else
     37 
     38 #include <bits/stl_pair.h>		// for std::pair
     39 #include <bits/uses_allocator.h>	// for std::allocator_arg_t
     40 #include <bits/utility.h>		// for std::tuple_size etc.
     41 #include <bits/invoke.h>		// for std::__invoke
     42 #if __cplusplus > 201703L
     43 # include <compare>
     44 # include <bits/ranges_util.h>		// for std::ranges::subrange
     45 #endif
     46 
     47 #define __glibcxx_want_constexpr_tuple
     48 #define __glibcxx_want_tuple_element_t
     49 #define __glibcxx_want_tuples_by_type
     50 #define __glibcxx_want_apply
     51 #define __glibcxx_want_make_from_tuple
     52 #define __glibcxx_want_ranges_zip
     53 #define __glibcxx_want_tuple_like
     54 #include <bits/version.h>
     55 
     56 namespace std _GLIBCXX_VISIBILITY(default)
     57 {
     58 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     59 
     60   /**
     61    *  @addtogroup utilities
     62    *  @{
     63    */
     64 
     65   template<typename... _Elements>
     66     class tuple;
     67 
     68   /// @cond undocumented
     69   template<typename _Tp>
     70     struct __is_empty_non_tuple : is_empty<_Tp> { };
     71 
     72   // Using EBO for elements that are tuples causes ambiguous base errors.
     73   template<typename _El0, typename... _El>
     74     struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
     75 
     76   // Use the Empty Base-class Optimization for empty, non-final types.
     77   template<typename _Tp>
     78     using __empty_not_final
     79     = __conditional_t<__is_final(_Tp), false_type,
     80 		      __is_empty_non_tuple<_Tp>>;
     81 
     82   template<size_t _Idx, typename _Head,
     83 	   bool = __empty_not_final<_Head>::value>
     84     struct _Head_base;
     85 
     86 #if __has_cpp_attribute(__no_unique_address__)
     87   template<size_t _Idx, typename _Head>
     88     struct _Head_base<_Idx, _Head, true>
     89     {
     90       constexpr _Head_base()
     91       : _M_head_impl() { }
     92 
     93       constexpr _Head_base(const _Head& __h)
     94       : _M_head_impl(__h) { }
     95 
     96       constexpr _Head_base(const _Head_base&) = default;
     97       constexpr _Head_base(_Head_base&&) = default;
     98 
     99       template<typename _UHead>
    100 	constexpr _Head_base(_UHead&& __h)
    101 	: _M_head_impl(std::forward<_UHead>(__h)) { }
    102 
    103       _GLIBCXX20_CONSTEXPR
    104       _Head_base(allocator_arg_t, __uses_alloc0)
    105       : _M_head_impl() { }
    106 
    107       template<typename _Alloc>
    108 	_GLIBCXX20_CONSTEXPR
    109 	_Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
    110 	: _M_head_impl(allocator_arg, *__a._M_a) { }
    111 
    112       template<typename _Alloc>
    113 	_GLIBCXX20_CONSTEXPR
    114 	_Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
    115 	: _M_head_impl(*__a._M_a) { }
    116 
    117       template<typename _UHead>
    118 	_GLIBCXX20_CONSTEXPR
    119 	_Head_base(__uses_alloc0, _UHead&& __uhead)
    120 	: _M_head_impl(std::forward<_UHead>(__uhead)) { }
    121 
    122       template<typename _Alloc, typename _UHead>
    123 	_GLIBCXX20_CONSTEXPR
    124 	_Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
    125 	: _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
    126 	{ }
    127 
    128       template<typename _Alloc, typename _UHead>
    129 	_GLIBCXX20_CONSTEXPR
    130 	_Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
    131 	: _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
    132 
    133       static constexpr _Head&
    134       _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
    135 
    136       static constexpr const _Head&
    137       _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
    138 
    139       [[__no_unique_address__]] _Head _M_head_impl;
    140     };
    141 #else
    142   template<size_t _Idx, typename _Head>
    143     struct _Head_base<_Idx, _Head, true>
    144     : public _Head
    145     {
    146       constexpr _Head_base()
    147       : _Head() { }
    148 
    149       constexpr _Head_base(const _Head& __h)
    150       : _Head(__h) { }
    151 
    152       constexpr _Head_base(const _Head_base&) = default;
    153       constexpr _Head_base(_Head_base&&) = default;
    154 
    155       template<typename _UHead>
    156         constexpr _Head_base(_UHead&& __h)
    157 	: _Head(std::forward<_UHead>(__h)) { }
    158 
    159       _GLIBCXX20_CONSTEXPR
    160       _Head_base(allocator_arg_t, __uses_alloc0)
    161       : _Head() { }
    162 
    163       template<typename _Alloc>
    164 	_GLIBCXX20_CONSTEXPR
    165 	_Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
    166 	: _Head(allocator_arg, *__a._M_a) { }
    167 
    168       template<typename _Alloc>
    169 	_GLIBCXX20_CONSTEXPR
    170 	_Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
    171 	: _Head(*__a._M_a) { }
    172 
    173       template<typename _UHead>
    174 	_GLIBCXX20_CONSTEXPR
    175 	_Head_base(__uses_alloc0, _UHead&& __uhead)
    176 	: _Head(std::forward<_UHead>(__uhead)) { }
    177 
    178       template<typename _Alloc, typename _UHead>
    179 	_GLIBCXX20_CONSTEXPR
    180 	_Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
    181 	: _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
    182 
    183       template<typename _Alloc, typename _UHead>
    184 	_GLIBCXX20_CONSTEXPR
    185 	_Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
    186 	: _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
    187 
    188       static constexpr _Head&
    189       _M_head(_Head_base& __b) noexcept { return __b; }
    190 
    191       static constexpr const _Head&
    192       _M_head(const _Head_base& __b) noexcept { return __b; }
    193     };
    194 #endif
    195 
    196   template<size_t _Idx, typename _Head>
    197     struct _Head_base<_Idx, _Head, false>
    198     {
    199       constexpr _Head_base()
    200       : _M_head_impl() { }
    201 
    202       constexpr _Head_base(const _Head& __h)
    203       : _M_head_impl(__h) { }
    204 
    205       constexpr _Head_base(const _Head_base&) = default;
    206       constexpr _Head_base(_Head_base&&) = default;
    207 
    208       template<typename _UHead>
    209         constexpr _Head_base(_UHead&& __h)
    210 	: _M_head_impl(std::forward<_UHead>(__h)) { }
    211 
    212       _GLIBCXX20_CONSTEXPR
    213       _Head_base(allocator_arg_t, __uses_alloc0)
    214       : _M_head_impl() { }
    215 
    216       template<typename _Alloc>
    217 	_GLIBCXX20_CONSTEXPR
    218 	_Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
    219 	: _M_head_impl(allocator_arg, *__a._M_a) { }
    220 
    221       template<typename _Alloc>
    222 	_GLIBCXX20_CONSTEXPR
    223 	_Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
    224 	: _M_head_impl(*__a._M_a) { }
    225 
    226       template<typename _UHead>
    227 	_GLIBCXX20_CONSTEXPR
    228 	_Head_base(__uses_alloc0, _UHead&& __uhead)
    229 	: _M_head_impl(std::forward<_UHead>(__uhead)) { }
    230 
    231       template<typename _Alloc, typename _UHead>
    232 	_GLIBCXX20_CONSTEXPR
    233 	_Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
    234 	: _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
    235 	{ }
    236 
    237       template<typename _Alloc, typename _UHead>
    238 	_GLIBCXX20_CONSTEXPR
    239 	_Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
    240 	: _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
    241 
    242       static constexpr _Head&
    243       _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
    244 
    245       static constexpr const _Head&
    246       _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
    247 
    248       _Head _M_head_impl;
    249     };
    250 
    251 #if __cpp_lib_tuple_like // >= C++23
    252   struct __tuple_like_tag_t { explicit __tuple_like_tag_t() = default; };
    253 
    254   // These forward declarations are used by the operator<=> overload for
    255   // tuple-like types.
    256   template<typename _Cat, typename _Tp, typename _Up>
    257     constexpr _Cat
    258     __tuple_cmp(const _Tp&, const _Up&, index_sequence<>);
    259 
    260   template<typename _Cat, typename _Tp, typename _Up,
    261 	   size_t _Idx0, size_t... _Idxs>
    262     constexpr _Cat
    263     __tuple_cmp(const _Tp& __t, const _Up& __u,
    264 		index_sequence<_Idx0, _Idxs...>);
    265 #endif // C++23
    266 
    267   /**
    268    * Contains the actual implementation of the @c tuple template, stored
    269    * as a recursive inheritance hierarchy from the first element (most
    270    * derived class) to the last (least derived class). The @c Idx
    271    * parameter gives the 0-based index of the element stored at this
    272    * point in the hierarchy; we use it to implement a constant-time
    273    * get() operation.
    274    */
    275   template<size_t _Idx, typename... _Elements>
    276     struct _Tuple_impl;
    277 
    278   /**
    279    * Recursive tuple implementation. Here we store the @c Head element
    280    * and derive from a @c Tuple_impl containing the remaining elements
    281    * (which contains the @c Tail).
    282    */
    283   template<size_t _Idx, typename _Head, typename... _Tail>
    284     struct _Tuple_impl<_Idx, _Head, _Tail...>
    285     : public _Tuple_impl<_Idx + 1, _Tail...>,
    286       private _Head_base<_Idx, _Head>
    287     {
    288       template<size_t, typename...> friend struct _Tuple_impl;
    289 
    290       typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
    291       typedef _Head_base<_Idx, _Head> _Base;
    292 
    293       static constexpr _Head&
    294       _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
    295 
    296       static constexpr const _Head&
    297       _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
    298 
    299       static constexpr _Inherited&
    300       _M_tail(_Tuple_impl& __t) noexcept { return __t; }
    301 
    302       static constexpr const _Inherited&
    303       _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
    304 
    305       constexpr _Tuple_impl()
    306       : _Inherited(), _Base() { }
    307 
    308       explicit constexpr
    309       _Tuple_impl(const _Head& __head, const _Tail&... __tail)
    310       : _Inherited(__tail...), _Base(__head)
    311       { }
    312 
    313       template<typename _UHead, typename... _UTail,
    314 	       typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
    315 	explicit constexpr
    316 	_Tuple_impl(_UHead&& __head, _UTail&&... __tail)
    317 	: _Inherited(std::forward<_UTail>(__tail)...),
    318 	  _Base(std::forward<_UHead>(__head))
    319 	{ }
    320 
    321       constexpr _Tuple_impl(const _Tuple_impl&) = default;
    322 
    323       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    324       // 2729. Missing SFINAE on std::pair::operator=
    325       _Tuple_impl& operator=(const _Tuple_impl&) = delete;
    326 
    327       _Tuple_impl(_Tuple_impl&&) = default;
    328 
    329       template<typename... _UElements>
    330 	constexpr
    331 	_Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
    332 	: _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
    333 	  _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
    334 	{ }
    335 
    336       template<typename _UHead, typename... _UTails>
    337 	constexpr
    338 	_Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
    339 	: _Inherited(std::move
    340 		     (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
    341 	  _Base(std::forward<_UHead>
    342 		(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
    343 	{ }
    344 
    345 #if __cpp_lib_ranges_zip // >= C++23
    346       template<typename... _UElements>
    347 	constexpr
    348 	_Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in)
    349 	: _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
    350 	  _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
    351 	{ }
    352 
    353       template<typename _UHead, typename... _UTails>
    354 	constexpr
    355 	_Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
    356 	: _Inherited(std::move
    357 		     (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
    358 	  _Base(std::forward<const _UHead>
    359 		(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
    360 	{ }
    361 #endif // C++23
    362 
    363 #if __cpp_lib_tuple_like // >= C++23
    364       template<typename _UTuple, size_t... _Is>
    365 	constexpr
    366 	_Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<_Is...>)
    367 	: _Tuple_impl(std::get<_Is>(std::forward<_UTuple>(__u))...)
    368 	{ }
    369 #endif // C++23
    370 
    371       template<typename _Alloc>
    372 	_GLIBCXX20_CONSTEXPR
    373 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
    374 	: _Inherited(__tag, __a),
    375 	  _Base(__tag, __use_alloc<_Head>(__a))
    376 	{ }
    377 
    378       template<typename _Alloc>
    379 	_GLIBCXX20_CONSTEXPR
    380 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    381 		    const _Head& __head, const _Tail&... __tail)
    382 	: _Inherited(__tag, __a, __tail...),
    383 	  _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
    384 	{ }
    385 
    386       template<typename _Alloc, typename _UHead, typename... _UTail,
    387 	       typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
    388 	_GLIBCXX20_CONSTEXPR
    389 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    390 		    _UHead&& __head, _UTail&&... __tail)
    391 	: _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
    392 	  _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
    393 		std::forward<_UHead>(__head))
    394 	{ }
    395 
    396       template<typename _Alloc>
    397 	_GLIBCXX20_CONSTEXPR
    398 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    399 		    const _Tuple_impl& __in)
    400 	: _Inherited(__tag, __a, _M_tail(__in)),
    401 	  _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
    402 	{ }
    403 
    404       template<typename _Alloc>
    405 	_GLIBCXX20_CONSTEXPR
    406 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    407 		    _Tuple_impl&& __in)
    408 	: _Inherited(__tag, __a, std::move(_M_tail(__in))),
    409 	  _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
    410 		std::forward<_Head>(_M_head(__in)))
    411 	{ }
    412 
    413       template<typename _Alloc, typename _UHead, typename... _UTails>
    414 	_GLIBCXX20_CONSTEXPR
    415 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    416 		    const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
    417 	: _Inherited(__tag, __a,
    418 		     _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
    419 	  _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
    420 		_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
    421 	{ }
    422 
    423       template<typename _Alloc, typename _UHead, typename... _UTails>
    424 	_GLIBCXX20_CONSTEXPR
    425 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    426 		    _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
    427 	: _Inherited(__tag, __a, std::move
    428 		     (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
    429 	  _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
    430 		std::forward<_UHead>
    431 		(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
    432 	{ }
    433 
    434 #if __cpp_lib_ranges_zip // >= C++23
    435       template<typename _Alloc, typename _UHead, typename... _UTails>
    436 	constexpr
    437 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    438 		    _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
    439 	: _Inherited(__tag, __a,
    440 		     _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
    441 	  _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
    442 		_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
    443 	{ }
    444 
    445       template<typename _Alloc, typename _UHead, typename... _UTails>
    446 	constexpr
    447 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    448 		    const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
    449 	: _Inherited(__tag, __a, std::move
    450 		     (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
    451 	  _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
    452 		std::forward<const _UHead>
    453 		(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
    454 	{ }
    455 #endif // C++23
    456 
    457 #if __cpp_lib_tuple_like // >= C++23
    458       template<typename _Alloc, typename _UTuple, size_t... _Is>
    459 	constexpr
    460 	_Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
    461 		    _UTuple&& __u, index_sequence<_Is...>)
    462 	: _Tuple_impl(__tag, __a, std::get<_Is>(std::forward<_UTuple>(__u))...)
    463 	{ }
    464 #endif // C++23
    465 
    466       template<typename... _UElements>
    467 	_GLIBCXX20_CONSTEXPR
    468 	void
    469 	_M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
    470 	{
    471 	  _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
    472 	  _M_tail(*this)._M_assign(
    473 	      _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
    474 	}
    475 
    476       template<typename _UHead, typename... _UTails>
    477 	_GLIBCXX20_CONSTEXPR
    478 	void
    479 	_M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
    480 	{
    481 	  _M_head(*this) = std::forward<_UHead>
    482 	    (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
    483 	  _M_tail(*this)._M_assign(
    484 	      std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
    485 	}
    486 
    487 #if __cpp_lib_ranges_zip // >= C++23
    488       template<typename... _UElements>
    489 	constexpr void
    490 	_M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const
    491 	{
    492 	  _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
    493 	  _M_tail(*this)._M_assign(
    494 	      _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
    495 	}
    496 
    497       template<typename _UHead, typename... _UTails>
    498 	constexpr void
    499 	_M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const
    500 	{
    501 	  _M_head(*this) = std::forward<_UHead>
    502 	    (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
    503 	  _M_tail(*this)._M_assign(
    504 	      std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
    505 	}
    506 #endif // C++23
    507 
    508 #if __cpp_lib_tuple_like // >= C++23
    509       template<typename _UTuple>
    510 	constexpr void
    511 	_M_assign(__tuple_like_tag_t __tag, _UTuple&& __u)
    512 	{
    513 	  _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
    514 	  _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
    515 	}
    516 
    517       template<typename _UTuple>
    518 	constexpr void
    519 	_M_assign(__tuple_like_tag_t __tag, _UTuple&& __u) const
    520 	{
    521 	  _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
    522 	  _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
    523 	}
    524 #endif // C++23
    525 
    526     protected:
    527       _GLIBCXX20_CONSTEXPR
    528       void
    529       _M_swap(_Tuple_impl& __in)
    530       {
    531 	using std::swap;
    532 	swap(_M_head(*this), _M_head(__in));
    533 	_Inherited::_M_swap(_M_tail(__in));
    534       }
    535 
    536 #if __cpp_lib_ranges_zip // >= C++23
    537       constexpr void
    538       _M_swap(const _Tuple_impl& __in) const
    539       {
    540 	using std::swap;
    541 	swap(_M_head(*this), _M_head(__in));
    542 	_Inherited::_M_swap(_M_tail(__in));
    543       }
    544 #endif // C++23
    545     };
    546 
    547   // Basis case of inheritance recursion.
    548   template<size_t _Idx, typename _Head>
    549     struct _Tuple_impl<_Idx, _Head>
    550     : private _Head_base<_Idx, _Head>
    551     {
    552       template<size_t, typename...> friend struct _Tuple_impl;
    553 
    554       typedef _Head_base<_Idx, _Head> _Base;
    555 
    556       static constexpr _Head&
    557       _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
    558 
    559       static constexpr const _Head&
    560       _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
    561 
    562       constexpr
    563       _Tuple_impl()
    564       : _Base() { }
    565 
    566       explicit constexpr
    567       _Tuple_impl(const _Head& __head)
    568       : _Base(__head)
    569       { }
    570 
    571       template<typename _UHead>
    572 	explicit constexpr
    573 	_Tuple_impl(_UHead&& __head)
    574 	: _Base(std::forward<_UHead>(__head))
    575 	{ }
    576 
    577       constexpr _Tuple_impl(const _Tuple_impl&) = default;
    578 
    579       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    580       // 2729. Missing SFINAE on std::pair::operator=
    581       _Tuple_impl& operator=(const _Tuple_impl&) = delete;
    582 
    583 #if _GLIBCXX_INLINE_VERSION
    584       _Tuple_impl(_Tuple_impl&&) = default;
    585 #else
    586       constexpr
    587       _Tuple_impl(_Tuple_impl&& __in)
    588       noexcept(is_nothrow_move_constructible<_Head>::value)
    589       : _Base(static_cast<_Base&&>(__in))
    590       { }
    591 #endif
    592 
    593       template<typename _UHead>
    594 	constexpr
    595 	_Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
    596 	: _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
    597 	{ }
    598 
    599       template<typename _UHead>
    600 	constexpr
    601 	_Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
    602 	: _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
    603 	{ }
    604 
    605 #if __cpp_lib_ranges_zip // >= C++23
    606       template<typename _UHead>
    607 	constexpr
    608 	_Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in)
    609 	: _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
    610 	{ }
    611 
    612       template<typename _UHead>
    613 	constexpr
    614 	_Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in)
    615 	: _Base(std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
    616 	{ }
    617 #endif // C++23
    618 
    619 #if __cpp_lib_tuple_like // >= C++23
    620       template<typename _UTuple>
    621 	constexpr
    622 	_Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<0>)
    623 	: _Tuple_impl(std::get<0>(std::forward<_UTuple>(__u)))
    624 	{ }
    625 #endif // C++23
    626 
    627       template<typename _Alloc>
    628 	_GLIBCXX20_CONSTEXPR
    629 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
    630 	: _Base(__tag, __use_alloc<_Head>(__a))
    631 	{ }
    632 
    633       template<typename _Alloc>
    634 	_GLIBCXX20_CONSTEXPR
    635 	_Tuple_impl(allocator_arg_t, const _Alloc& __a,
    636 		    const _Head& __head)
    637 	: _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
    638 	{ }
    639 
    640       template<typename _Alloc, typename _UHead>
    641 	_GLIBCXX20_CONSTEXPR
    642 	_Tuple_impl(allocator_arg_t, const _Alloc& __a,
    643 		    _UHead&& __head)
    644 	: _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
    645 		std::forward<_UHead>(__head))
    646 	{ }
    647 
    648       template<typename _Alloc>
    649 	_GLIBCXX20_CONSTEXPR
    650 	_Tuple_impl(allocator_arg_t, const _Alloc& __a,
    651 		    const _Tuple_impl& __in)
    652 	: _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
    653 	{ }
    654 
    655       template<typename _Alloc>
    656 	_GLIBCXX20_CONSTEXPR
    657 	_Tuple_impl(allocator_arg_t, const _Alloc& __a,
    658 		    _Tuple_impl&& __in)
    659 	: _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
    660 		std::forward<_Head>(_M_head(__in)))
    661 	{ }
    662 
    663       template<typename _Alloc, typename _UHead>
    664 	_GLIBCXX20_CONSTEXPR
    665 	_Tuple_impl(allocator_arg_t, const _Alloc& __a,
    666 		    const _Tuple_impl<_Idx, _UHead>& __in)
    667 	: _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
    668 		_Tuple_impl<_Idx, _UHead>::_M_head(__in))
    669 	{ }
    670 
    671       template<typename _Alloc, typename _UHead>
    672 	_GLIBCXX20_CONSTEXPR
    673 	_Tuple_impl(allocator_arg_t, const _Alloc& __a,
    674 		    _Tuple_impl<_Idx, _UHead>&& __in)
    675 	: _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
    676 		std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
    677 	{ }
    678 
    679 #if __cpp_lib_ranges_zip // >= C++23
    680       template<typename _Alloc, typename _UHead>
    681 	constexpr
    682 	_Tuple_impl(allocator_arg_t, const _Alloc& __a,
    683 		    _Tuple_impl<_Idx, _UHead>& __in)
    684 	: _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
    685 		_Tuple_impl<_Idx, _UHead>::_M_head(__in))
    686 	{ }
    687 
    688       template<typename _Alloc, typename _UHead>
    689 	constexpr
    690 	_Tuple_impl(allocator_arg_t, const _Alloc& __a,
    691 		    const _Tuple_impl<_Idx, _UHead>&& __in)
    692 	: _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
    693 		std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
    694 	{ }
    695 #endif // C++23
    696 
    697 #if __cpp_lib_tuple_like // >= C++23
    698       template<typename _Alloc, typename _UTuple>
    699 	constexpr
    700 	_Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
    701 		    _UTuple&& __u, index_sequence<0>)
    702 	: _Tuple_impl(__tag, __a, std::get<0>(std::forward<_UTuple>(__u)))
    703 	{ }
    704 #endif // C++23
    705 
    706       template<typename _UHead>
    707 	_GLIBCXX20_CONSTEXPR
    708 	void
    709 	_M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
    710 	{
    711 	  _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
    712 	}
    713 
    714       template<typename _UHead>
    715 	_GLIBCXX20_CONSTEXPR
    716 	void
    717 	_M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
    718 	{
    719 	  _M_head(*this)
    720 	    = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
    721 	}
    722 
    723 #if __cpp_lib_ranges_zip // >= C++23
    724       template<typename _UHead>
    725 	constexpr void
    726 	_M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const
    727 	{
    728 	  _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
    729 	}
    730 
    731       template<typename _UHead>
    732 	constexpr void
    733 	_M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const
    734 	{
    735 	  _M_head(*this)
    736 	    = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
    737 	}
    738 #endif // C++23
    739 
    740 #if __cpp_lib_tuple_like // >= C++23
    741     template<typename _UTuple>
    742       constexpr void
    743       _M_assign(__tuple_like_tag_t, _UTuple&& __u)
    744       { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
    745 
    746     template<typename _UTuple>
    747       constexpr void
    748       _M_assign(__tuple_like_tag_t, _UTuple&& __u) const
    749       { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
    750 #endif // C++23
    751 
    752     protected:
    753       _GLIBCXX20_CONSTEXPR
    754       void
    755       _M_swap(_Tuple_impl& __in)
    756       {
    757 	using std::swap;
    758 	swap(_M_head(*this), _M_head(__in));
    759       }
    760 
    761 #if __cpp_lib_ranges_zip // >= C++23
    762       constexpr void
    763       _M_swap(const _Tuple_impl& __in) const
    764       {
    765 	using std::swap;
    766 	swap(_M_head(*this), _M_head(__in));
    767       }
    768 #endif // C++23
    769     };
    770 
    771   // Concept utility functions, reused in conditionally-explicit
    772   // constructors.
    773   template<bool, typename... _Types>
    774     struct _TupleConstraints
    775     {
    776       template<typename... _UTypes>
    777 	using __constructible = __and_<is_constructible<_Types, _UTypes>...>;
    778 
    779       template<typename... _UTypes>
    780 	using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
    781 
    782       // Constraint for a non-explicit constructor.
    783       // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
    784       // and every Ui is implicitly convertible to Ti.
    785       template<typename... _UTypes>
    786 	static constexpr bool __is_implicitly_constructible()
    787 	{
    788 	  return __and_<__constructible<_UTypes...>,
    789 			__convertible<_UTypes...>
    790 			>::value;
    791 	}
    792 
    793       // Constraint for a non-explicit constructor.
    794       // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
    795       // but not every Ui is implicitly convertible to Ti.
    796       template<typename... _UTypes>
    797 	static constexpr bool __is_explicitly_constructible()
    798 	{
    799 	  return __and_<__constructible<_UTypes...>,
    800 			__not_<__convertible<_UTypes...>>
    801 			>::value;
    802 	}
    803 
    804       static constexpr bool __is_implicitly_default_constructible()
    805       {
    806 	return __and_<std::__is_implicitly_default_constructible<_Types>...
    807 		      >::value;
    808       }
    809 
    810       static constexpr bool __is_explicitly_default_constructible()
    811       {
    812 	return __and_<is_default_constructible<_Types>...,
    813 		      __not_<__and_<
    814 			std::__is_implicitly_default_constructible<_Types>...>
    815 		      >>::value;
    816       }
    817     };
    818 
    819   // Partial specialization used when a required precondition isn't met,
    820   // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
    821   template<typename... _Types>
    822     struct _TupleConstraints<false, _Types...>
    823     {
    824       template<typename... _UTypes>
    825 	static constexpr bool __is_implicitly_constructible()
    826 	{ return false; }
    827 
    828       template<typename... _UTypes>
    829 	static constexpr bool __is_explicitly_constructible()
    830 	{ return false; }
    831     };
    832   /// @endcond
    833 
    834   /// Primary class template, tuple
    835   template<typename... _Elements>
    836     class tuple : public _Tuple_impl<0, _Elements...>
    837     {
    838       using _Inherited = _Tuple_impl<0, _Elements...>;
    839 
    840 #if __cpp_concepts && __cpp_consteval && __cpp_conditional_explicit // >= C++20
    841       template<typename... _UTypes>
    842 	static consteval bool
    843 	__constructible()
    844 	{
    845 	  if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
    846 	    return __and_v<is_constructible<_Elements, _UTypes>...>;
    847 	  else
    848 	    return false;
    849 	}
    850 
    851       template<typename... _UTypes>
    852 	static consteval bool
    853 	__nothrow_constructible()
    854 	{
    855 	  if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
    856 	    return __and_v<is_nothrow_constructible<_Elements, _UTypes>...>;
    857 	  else
    858 	    return false;
    859 	}
    860 
    861       template<typename... _UTypes>
    862 	static consteval bool
    863 	__convertible()
    864 	{
    865 	  if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
    866 	    return __and_v<is_convertible<_UTypes, _Elements>...>;
    867 	  else
    868 	    return false;
    869 	}
    870 
    871       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    872       // 3121. tuple constructor constraints for UTypes&&... overloads
    873       template<typename... _UTypes>
    874 	static consteval bool
    875 	__disambiguating_constraint()
    876 	{
    877 	  if constexpr (sizeof...(_Elements) != sizeof...(_UTypes))
    878 	    return false;
    879 	  else if constexpr (sizeof...(_Elements) == 1)
    880 	    {
    881 	      using _U0 = typename _Nth_type<0, _UTypes...>::type;
    882 	      return !is_same_v<remove_cvref_t<_U0>, tuple>;
    883 	    }
    884 	  else if constexpr (sizeof...(_Elements) < 4)
    885 	    {
    886 	      using _U0 = typename _Nth_type<0, _UTypes...>::type;
    887 	      if constexpr (!is_same_v<remove_cvref_t<_U0>, allocator_arg_t>)
    888 		return true;
    889 	      else
    890 		{
    891 		  using _T0 = typename _Nth_type<0, _Elements...>::type;
    892 		  return is_same_v<remove_cvref_t<_T0>, allocator_arg_t>;
    893 		}
    894 	    }
    895 	  return true;
    896 	}
    897 
    898       // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
    899       // and the single element in Types can be initialized from TUPLE,
    900       // or is the same type as tuple_element_t<0, TUPLE>.
    901       template<typename _Tuple>
    902 	static consteval bool
    903 	__use_other_ctor()
    904 	{
    905 	  if constexpr (sizeof...(_Elements) != 1)
    906 	    return false;
    907 	  else if constexpr (is_same_v<remove_cvref_t<_Tuple>, tuple>)
    908 	    return true; // Should use a copy/move constructor instead.
    909 	  else
    910 	    {
    911 	      using _Tp = typename _Nth_type<0, _Elements...>::type;
    912 	      if constexpr (is_convertible_v<_Tuple, _Tp>)
    913 		return true;
    914 	      else if constexpr (is_constructible_v<_Tp, _Tuple>)
    915 		return true;
    916 	    }
    917 	  return false;
    918 	}
    919 
    920       template<typename... _Up>
    921 	static consteval bool
    922 	__dangles()
    923 	{
    924 #if __has_builtin(__reference_constructs_from_temporary)
    925 	  return (__reference_constructs_from_temporary(_Elements, _Up&&)
    926 		    || ...);
    927 #else
    928 	  return false;
    929 #endif
    930 	}
    931 
    932 #if __cpp_lib_tuple_like // >= C++23
    933       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    934       // 4045. tuple can create dangling references from tuple-like
    935       template<typename _UTuple>
    936 	static consteval bool
    937 	__dangles_from_tuple_like()
    938 	{
    939 	  return []<size_t... _Is>(index_sequence<_Is...>) {
    940 	    return __dangles<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
    941 	  }(index_sequence_for<_Elements...>{});
    942 	}
    943 
    944       template<typename _UTuple>
    945 	static consteval bool
    946 	__constructible_from_tuple_like()
    947 	{
    948 	  return []<size_t... _Is>(index_sequence<_Is...>) {
    949 	    return __constructible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
    950 	  }(index_sequence_for<_Elements...>{});
    951 	}
    952 
    953       template<typename _UTuple>
    954 	static consteval bool
    955 	__convertible_from_tuple_like()
    956 	{
    957 	  return []<size_t... _Is>(index_sequence<_Is...>) {
    958 	    return __convertible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
    959 	  }(index_sequence_for<_Elements...>{});
    960 	}
    961 #endif // C++23
    962 
    963     public:
    964       constexpr
    965       explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
    966       tuple()
    967       noexcept((is_nothrow_default_constructible_v<_Elements> && ...))
    968       requires (is_default_constructible_v<_Elements> && ...)
    969       : _Inherited()
    970       { }
    971 
    972       // Defined as a template to work around PR libstdc++/116440.
    973       template<typename = void>
    974 	constexpr explicit(!__convertible<const _Elements&...>())
    975 	tuple(const _Elements&... __elements)
    976 	noexcept(__nothrow_constructible<const _Elements&...>())
    977 	requires (__constructible<const _Elements&...>())
    978 	: _Inherited(__elements...)
    979 	{ }
    980 
    981       template<typename... _UTypes>
    982 	requires (__disambiguating_constraint<_UTypes...>())
    983 	  && (__constructible<_UTypes...>())
    984 	  && (!__dangles<_UTypes...>())
    985 	constexpr explicit(!__convertible<_UTypes...>())
    986 	tuple(_UTypes&&... __u)
    987 	noexcept(__nothrow_constructible<_UTypes...>())
    988 	: _Inherited(std::forward<_UTypes>(__u)...)
    989 	{ }
    990 
    991       template<typename... _UTypes>
    992 	requires (__disambiguating_constraint<_UTypes...>())
    993 	  && (__constructible<_UTypes...>())
    994 	  && (__dangles<_UTypes...>())
    995 	tuple(_UTypes&&...) = delete;
    996 
    997       constexpr tuple(const tuple&) = default;
    998 
    999       constexpr tuple(tuple&&) = default;
   1000 
   1001       template<typename... _UTypes>
   1002 	requires (__constructible<const _UTypes&...>())
   1003 	  && (!__use_other_ctor<const tuple<_UTypes...>&>())
   1004 	  && (!__dangles<const _UTypes&...>())
   1005 	constexpr explicit(!__convertible<const _UTypes&...>())
   1006 	tuple(const tuple<_UTypes...>& __u)
   1007 	noexcept(__nothrow_constructible<const _UTypes&...>())
   1008 	: _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
   1009 	{ }
   1010 
   1011       template<typename... _UTypes>
   1012 	requires (__constructible<const _UTypes&...>())
   1013 	  && (!__use_other_ctor<const tuple<_UTypes...>&>())
   1014 	  && (__dangles<const _UTypes&...>())
   1015 	tuple(const tuple<_UTypes...>&) = delete;
   1016 
   1017       template<typename... _UTypes>
   1018 	requires (__constructible<_UTypes...>())
   1019 	  && (!__use_other_ctor<tuple<_UTypes...>>())
   1020 	  && (!__dangles<_UTypes...>())
   1021 	constexpr explicit(!__convertible<_UTypes...>())
   1022 	tuple(tuple<_UTypes...>&& __u)
   1023 	noexcept(__nothrow_constructible<_UTypes...>())
   1024 	: _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
   1025 	{ }
   1026 
   1027       template<typename... _UTypes>
   1028 	requires (__constructible<_UTypes...>())
   1029 	  && (!__use_other_ctor<tuple<_UTypes...>>())
   1030 	  && (__dangles<_UTypes...>())
   1031 	tuple(tuple<_UTypes...>&&) = delete;
   1032 
   1033 #if __cpp_lib_ranges_zip // >= C++23
   1034       template<typename... _UTypes>
   1035 	requires (__constructible<_UTypes&...>())
   1036 	  && (!__use_other_ctor<tuple<_UTypes...>&>())
   1037 	  && (!__dangles<_UTypes&...>())
   1038 	constexpr explicit(!__convertible<_UTypes&...>())
   1039 	tuple(tuple<_UTypes...>& __u)
   1040 	noexcept(__nothrow_constructible<_UTypes&...>())
   1041 	: _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
   1042 	{ }
   1043 
   1044       template<typename... _UTypes>
   1045 	requires (__constructible<_UTypes&...>())
   1046 	  && (!__use_other_ctor<tuple<_UTypes...>&>())
   1047 	  && (__dangles<_UTypes&...>())
   1048 	tuple(tuple<_UTypes...>&) = delete;
   1049 
   1050       template<typename... _UTypes>
   1051 	requires (__constructible<const _UTypes...>())
   1052 	  && (!__use_other_ctor<const tuple<_UTypes...>>())
   1053 	  && (!__dangles<const _UTypes...>())
   1054 	constexpr explicit(!__convertible<const _UTypes...>())
   1055 	tuple(const tuple<_UTypes...>&& __u)
   1056 	noexcept(__nothrow_constructible<const _UTypes...>())
   1057 	: _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
   1058 	{ }
   1059 
   1060       template<typename... _UTypes>
   1061 	requires (__constructible<const _UTypes...>())
   1062 	  && (!__use_other_ctor<const tuple<_UTypes...>>())
   1063 	  && (__dangles<const _UTypes...>())
   1064 	tuple(const tuple<_UTypes...>&&) = delete;
   1065 #endif // C++23
   1066 
   1067       template<typename _U1, typename _U2>
   1068 	requires (sizeof...(_Elements) == 2)
   1069 	  && (__constructible<const _U1&, const _U2&>())
   1070 	  && (!__dangles<const _U1&, const _U2&>())
   1071 	constexpr explicit(!__convertible<const _U1&, const _U2&>())
   1072 	tuple(const pair<_U1, _U2>& __u)
   1073 	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
   1074 	: _Inherited(__u.first, __u.second)
   1075 	{ }
   1076 
   1077       template<typename _U1, typename _U2>
   1078 	requires (sizeof...(_Elements) == 2)
   1079 	  && (__constructible<const _U1&, const _U2&>())
   1080 	  && (__dangles<const _U1&, const _U2&>())
   1081 	tuple(const pair<_U1, _U2>&) = delete;
   1082 
   1083       template<typename _U1, typename _U2>
   1084 	requires (sizeof...(_Elements) == 2)
   1085 	  && (__constructible<_U1, _U2>())
   1086 	  && (!__dangles<_U1, _U2>())
   1087 	constexpr explicit(!__convertible<_U1, _U2>())
   1088 	tuple(pair<_U1, _U2>&& __u)
   1089 	noexcept(__nothrow_constructible<_U1, _U2>())
   1090 	: _Inherited(std::forward<_U1>(__u.first),
   1091 		     std::forward<_U2>(__u.second))
   1092 	{ }
   1093 
   1094       template<typename _U1, typename _U2>
   1095 	requires (sizeof...(_Elements) == 2)
   1096 	  && (__constructible<_U1, _U2>())
   1097 	  && (__dangles<_U1, _U2>())
   1098 	tuple(pair<_U1, _U2>&&) = delete;
   1099 
   1100 #if __cpp_lib_ranges_zip // >= C++23
   1101       template<typename _U1, typename _U2>
   1102 	requires (sizeof...(_Elements) == 2)
   1103 	  && (__constructible<_U1&, _U2&>())
   1104 	  && (!__dangles<_U1&, _U2&>())
   1105 	constexpr explicit(!__convertible<_U1&, _U2&>())
   1106 	tuple(pair<_U1, _U2>& __u)
   1107 	noexcept(__nothrow_constructible<_U1&, _U2&>())
   1108 	: _Inherited(__u.first, __u.second)
   1109 	{ }
   1110 
   1111       template<typename _U1, typename _U2>
   1112 	requires (sizeof...(_Elements) == 2)
   1113 	  && (__constructible<_U1&, _U2&>())
   1114 	  && (__dangles<_U1&, _U2&>())
   1115 	tuple(pair<_U1, _U2>&) = delete;
   1116 
   1117       template<typename _U1, typename _U2>
   1118 	requires (sizeof...(_Elements) == 2)
   1119 	  && (__constructible<const _U1, const _U2>())
   1120 	  && (!__dangles<const _U1, const _U2>())
   1121 	constexpr explicit(!__convertible<const _U1, const _U2>())
   1122 	tuple(const pair<_U1, _U2>&& __u)
   1123 	noexcept(__nothrow_constructible<const _U1, const _U2>())
   1124 	: _Inherited(std::forward<const _U1>(__u.first),
   1125 		     std::forward<const _U2>(__u.second))
   1126 	{ }
   1127 
   1128       template<typename _U1, typename _U2>
   1129 	requires (sizeof...(_Elements) == 2)
   1130 	  && (__constructible<const _U1, const _U2>())
   1131 	  && (__dangles<const _U1, const _U2>())
   1132 	tuple(const pair<_U1, _U2>&&) = delete;
   1133 #endif // C++23
   1134 
   1135 #if __cpp_lib_tuple_like // >= C++23
   1136       template<__eligible_tuple_like<tuple> _UTuple>
   1137 	requires (__constructible_from_tuple_like<_UTuple>())
   1138 	  && (!__use_other_ctor<_UTuple>())
   1139 	  && (!__dangles_from_tuple_like<_UTuple>())
   1140 	constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
   1141 	tuple(_UTuple&& __u)
   1142 	: _Inherited(__tuple_like_tag_t{},
   1143 		     std::forward<_UTuple>(__u),
   1144 		     index_sequence_for<_Elements...>{})
   1145 	{ }
   1146 
   1147       template<__eligible_tuple_like<tuple> _UTuple>
   1148 	requires (__constructible_from_tuple_like<_UTuple>())
   1149 	  && (!__use_other_ctor<_UTuple>())
   1150 	  && (__dangles_from_tuple_like<_UTuple>())
   1151 	tuple(_UTuple&&) = delete;
   1152 #endif // C++23
   1153 
   1154       // Allocator-extended constructors.
   1155 
   1156       template<typename _Alloc>
   1157 	constexpr
   1158 	explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
   1159 	tuple(allocator_arg_t __tag, const _Alloc& __a)
   1160 	requires (is_default_constructible_v<_Elements> && ...)
   1161 	: _Inherited(__tag, __a)
   1162 	{ }
   1163 
   1164       template<typename _Alloc>
   1165 	constexpr explicit(!__convertible<const _Elements&...>())
   1166 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1167 	      const _Elements&... __elements)
   1168 	requires (__constructible<const _Elements&...>())
   1169 	: _Inherited(__tag, __a, __elements...)
   1170 	{ }
   1171 
   1172       template<typename _Alloc, typename... _UTypes>
   1173 	requires (__disambiguating_constraint<_UTypes...>())
   1174 	  && (__constructible<_UTypes...>())
   1175 	  && (!__dangles<_UTypes...>())
   1176 	constexpr explicit(!__convertible<_UTypes...>())
   1177 	tuple(allocator_arg_t __tag, const _Alloc& __a, _UTypes&&... __u)
   1178 	: _Inherited(__tag, __a, std::forward<_UTypes>(__u)...)
   1179 	{ }
   1180 
   1181       template<typename _Alloc, typename... _UTypes>
   1182 	requires (__disambiguating_constraint<_UTypes...>())
   1183 	  && (__constructible<_UTypes...>())
   1184 	  && (__dangles<_UTypes...>())
   1185 	tuple(allocator_arg_t, const _Alloc&, _UTypes&&...) = delete;
   1186 
   1187       template<typename _Alloc>
   1188 	constexpr
   1189 	tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __u)
   1190 	: _Inherited(__tag, __a, static_cast<const _Inherited&>(__u))
   1191 	{ }
   1192 
   1193       template<typename _Alloc>
   1194 	requires (__constructible<_Elements...>())
   1195 	constexpr
   1196 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __u)
   1197 	: _Inherited(__tag, __a, static_cast<_Inherited&&>(__u))
   1198 	{ }
   1199 
   1200       template<typename _Alloc, typename... _UTypes>
   1201 	requires (__constructible<const _UTypes&...>())
   1202 	  && (!__use_other_ctor<const tuple<_UTypes...>&>())
   1203 	  && (!__dangles<const _UTypes&...>())
   1204 	constexpr explicit(!__convertible<const _UTypes&...>())
   1205 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1206 	      const tuple<_UTypes...>& __u)
   1207 	: _Inherited(__tag, __a,
   1208 		     static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
   1209 	{ }
   1210 
   1211       template<typename _Alloc, typename... _UTypes>
   1212 	requires (__constructible<const _UTypes&...>())
   1213 	  && (!__use_other_ctor<const tuple<_UTypes...>&>())
   1214 	  && (__dangles<const _UTypes&...>())
   1215 	tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&) = delete;
   1216 
   1217       template<typename _Alloc, typename... _UTypes>
   1218 	requires (__constructible<_UTypes...>())
   1219 	  && (!__use_other_ctor<tuple<_UTypes...>>())
   1220 	  && (!__dangles<_UTypes...>())
   1221 	constexpr explicit(!__use_other_ctor<tuple<_UTypes...>>())
   1222 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>&& __u)
   1223 	: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
   1224 	{ }
   1225 
   1226       template<typename _Alloc, typename... _UTypes>
   1227 	requires (__constructible<_UTypes...>())
   1228 	  && (!__use_other_ctor<tuple<_UTypes...>>())
   1229 	  && (__dangles<_UTypes...>())
   1230 	tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&&) = delete;
   1231 
   1232 #if __cpp_lib_ranges_zip // >= C++23
   1233       template<typename _Alloc, typename... _UTypes>
   1234 	requires (__constructible<_UTypes&...>())
   1235 	  && (!__use_other_ctor<tuple<_UTypes...>&>())
   1236 	  && (!__dangles<_UTypes&...>())
   1237 	constexpr explicit(!__convertible<_UTypes&...>())
   1238 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>& __u)
   1239 	: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
   1240 	{ }
   1241 
   1242       template<typename _Alloc, typename... _UTypes>
   1243 	requires (__constructible<_UTypes&...>())
   1244 	  && (!__use_other_ctor<tuple<_UTypes...>&>())
   1245 	  && (__dangles<_UTypes&...>())
   1246 	tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&) = delete;
   1247 
   1248       template<typename _Alloc, typename... _UTypes>
   1249 	requires (__constructible<const _UTypes...>())
   1250 	  && (!__use_other_ctor<const tuple<_UTypes...>>())
   1251 	  && (!__dangles<const _UTypes...>())
   1252 	constexpr explicit(!__convertible<const _UTypes...>())
   1253 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1254 	      const tuple<_UTypes...>&& __u)
   1255 	: _Inherited(__tag, __a,
   1256 		     static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
   1257 	{ }
   1258 
   1259       template<typename _Alloc, typename... _UTypes>
   1260 	requires (__constructible<const _UTypes...>())
   1261 	  && (!__use_other_ctor<const tuple<_UTypes...>>())
   1262 	  && (__dangles<const _UTypes...>())
   1263 	tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&&) = delete;
   1264 #endif // C++23
   1265 
   1266       template<typename _Alloc, typename _U1, typename _U2>
   1267 	requires (sizeof...(_Elements) == 2)
   1268 	  && (__constructible<const _U1&, const _U2&>())
   1269 	  && (!__dangles<const _U1&, const _U2&>())
   1270 	constexpr explicit(!__convertible<const _U1&, const _U2&>())
   1271 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1272 	      const pair<_U1, _U2>& __u)
   1273 	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
   1274 	: _Inherited(__tag, __a, __u.first, __u.second)
   1275 	{ }
   1276 
   1277       template<typename _Alloc, typename _U1, typename _U2>
   1278 	requires (sizeof...(_Elements) == 2)
   1279 	  && (__constructible<const _U1&, const _U2&>())
   1280 	  && (__dangles<const _U1&, const _U2&>())
   1281 	tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&) = delete;
   1282 
   1283       template<typename _Alloc, typename _U1, typename _U2>
   1284 	requires (sizeof...(_Elements) == 2)
   1285 	  && (__constructible<_U1, _U2>())
   1286 	  && (!__dangles<_U1, _U2>())
   1287 	constexpr explicit(!__convertible<_U1, _U2>())
   1288 	tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __u)
   1289 	noexcept(__nothrow_constructible<_U1, _U2>())
   1290 	: _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
   1291 	{ }
   1292 
   1293       template<typename _Alloc, typename _U1, typename _U2>
   1294 	requires (sizeof...(_Elements) == 2)
   1295 	  && (__constructible<_U1, _U2>())
   1296 	  && (__dangles<_U1, _U2>())
   1297 	tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&) = delete;
   1298 
   1299 #if __cpp_lib_ranges_zip // >= C++23
   1300       template<typename _Alloc, typename _U1, typename _U2>
   1301 	requires (sizeof...(_Elements) == 2)
   1302 	  && (__constructible<_U1&, _U2&>())
   1303 	  && (!__dangles<_U1&, _U2&>())
   1304 	constexpr explicit(!__convertible<_U1&, _U2&>())
   1305 	tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>& __u)
   1306 	noexcept(__nothrow_constructible<_U1&, _U2&>())
   1307 	: _Inherited(__tag, __a, __u.first, __u.second)
   1308 	{ }
   1309 
   1310       template<typename _Alloc, typename _U1, typename _U2>
   1311 	requires (sizeof...(_Elements) == 2)
   1312 	  && (__constructible<_U1&, _U2&>())
   1313 	  && (__dangles<_U1&, _U2&>())
   1314 	tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete;
   1315 
   1316       template<typename _Alloc, typename _U1, typename _U2>
   1317 	requires (sizeof...(_Elements) == 2)
   1318 	  && (__constructible<const _U1, const _U2>())
   1319 	  && (!__dangles<const _U1, const _U2>())
   1320 	constexpr explicit(!__convertible<const _U1, const _U2>())
   1321 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1322 	const pair<_U1, _U2>&& __u)
   1323 	noexcept(__nothrow_constructible<const _U1, const _U2>())
   1324 	: _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
   1325 	{ }
   1326 
   1327       template<typename _Alloc, typename _U1, typename _U2>
   1328 	requires (sizeof...(_Elements) == 2)
   1329 	  && (__constructible<const _U1, const _U2>())
   1330 	  && (__dangles<const _U1, const _U2>())
   1331 	tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&&) = delete;
   1332 #endif // C++23
   1333 
   1334 #if __cpp_lib_tuple_like // >= C++23
   1335       template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
   1336 	requires (__constructible_from_tuple_like<_UTuple>())
   1337 	  && (!__use_other_ctor<_UTuple>())
   1338 	  && (!__dangles_from_tuple_like<_UTuple>())
   1339 	constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
   1340 	tuple(allocator_arg_t __tag, const _Alloc& __a, _UTuple&& __u)
   1341 	: _Inherited(__tuple_like_tag_t{},
   1342 		     __tag, __a, std::forward<_UTuple>(__u),
   1343 		     index_sequence_for<_Elements...>{})
   1344 	{ }
   1345 
   1346       template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
   1347 	requires (__constructible_from_tuple_like<_UTuple>())
   1348 	  && (!__use_other_ctor<_UTuple>())
   1349 	  && (__dangles_from_tuple_like<_UTuple>())
   1350 	tuple(allocator_arg_t, const _Alloc&, _UTuple&&) = delete;
   1351 #endif // C++23
   1352 
   1353 #else // !(concepts && conditional_explicit)
   1354 
   1355       template<bool _Cond>
   1356 	using _TCC = _TupleConstraints<_Cond, _Elements...>;
   1357 
   1358       // Constraint for non-explicit default constructor
   1359       template<bool _Dummy>
   1360 	using _ImplicitDefaultCtor = __enable_if_t<
   1361 	  _TCC<_Dummy>::__is_implicitly_default_constructible(),
   1362 	  bool>;
   1363 
   1364       // Constraint for explicit default constructor
   1365       template<bool _Dummy>
   1366 	using _ExplicitDefaultCtor = __enable_if_t<
   1367 	  _TCC<_Dummy>::__is_explicitly_default_constructible(),
   1368 	  bool>;
   1369 
   1370       // Constraint for non-explicit constructors
   1371       template<bool _Cond, typename... _Args>
   1372 	using _ImplicitCtor = __enable_if_t<
   1373 	  _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
   1374 	  bool>;
   1375 
   1376       // Constraint for non-explicit constructors
   1377       template<bool _Cond, typename... _Args>
   1378 	using _ExplicitCtor = __enable_if_t<
   1379 	  _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
   1380 	  bool>;
   1381 
   1382       // Condition for noexcept-specifier of a constructor.
   1383       template<typename... _UElements>
   1384 	static constexpr bool __nothrow_constructible()
   1385 	{
   1386 	  return
   1387 	    __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
   1388 	}
   1389 
   1390       // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
   1391       template<typename _Up>
   1392 	static constexpr bool __valid_args()
   1393 	{
   1394 	  return sizeof...(_Elements) == 1
   1395 	    && !is_same<tuple, __remove_cvref_t<_Up>>::value;
   1396 	}
   1397 
   1398       // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
   1399       template<typename, typename, typename... _Tail>
   1400 	static constexpr bool __valid_args()
   1401 	{ return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
   1402 
   1403       /* Constraint for constructors with a tuple<UTypes...> parameter ensures
   1404        * that the constructor is only viable when it would not interfere with
   1405        * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
   1406        * Such constructors are only viable if:
   1407        * either sizeof...(Types) != 1,
   1408        * or (when Types... expands to T and UTypes... expands to U)
   1409        * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
   1410        * and is_same_v<T, U> are all false.
   1411        */
   1412       template<typename _Tuple, typename = tuple,
   1413 	       typename = __remove_cvref_t<_Tuple>>
   1414 	struct _UseOtherCtor
   1415 	: false_type
   1416 	{ };
   1417       // If TUPLE is convertible to the single element in *this,
   1418       // then TUPLE should match tuple(UTypes&&...) instead.
   1419       template<typename _Tuple, typename _Tp, typename _Up>
   1420 	struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
   1421 	: __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
   1422 	{ };
   1423       // If TUPLE and *this each have a single element of the same type,
   1424       // then TUPLE should match a copy/move constructor instead.
   1425       template<typename _Tuple, typename _Tp>
   1426 	struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
   1427 	: true_type
   1428 	{ };
   1429 
   1430       // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
   1431       // and the single element in Types can be initialized from TUPLE,
   1432       // or is the same type as tuple_element_t<0, TUPLE>.
   1433       template<typename _Tuple>
   1434 	static constexpr bool __use_other_ctor()
   1435 	{ return _UseOtherCtor<_Tuple>::value; }
   1436 
   1437       /// @cond undocumented
   1438 #undef __glibcxx_no_dangling_refs
   1439 #if __has_builtin(__reference_constructs_from_temporary) \
   1440       && defined _GLIBCXX_DEBUG
   1441       // Error if construction from U... would create a dangling ref.
   1442 # if __cpp_fold_expressions
   1443 #  define __glibcxx_dangling_refs(U) \
   1444   (__reference_constructs_from_temporary(_Elements, U) || ...)
   1445 # else
   1446 #  define __glibcxx_dangling_refs(U) \
   1447   __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \
   1448        >...>::value
   1449 # endif
   1450 # define __glibcxx_no_dangling_refs(U) \
   1451   static_assert(!__glibcxx_dangling_refs(U), \
   1452 		"std::tuple constructor creates a dangling reference")
   1453 #else
   1454 # define __glibcxx_no_dangling_refs(U)
   1455 #endif
   1456       /// @endcond
   1457 
   1458     public:
   1459       template<typename _Dummy = void,
   1460 	       _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
   1461 	constexpr
   1462 	tuple()
   1463 	noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
   1464 	: _Inherited() { }
   1465 
   1466       template<typename _Dummy = void,
   1467 	       _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
   1468 	explicit constexpr
   1469 	tuple()
   1470 	noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
   1471 	: _Inherited() { }
   1472 
   1473       template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
   1474 	       _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
   1475 	constexpr
   1476 	tuple(const _Elements&... __elements)
   1477 	noexcept(__nothrow_constructible<const _Elements&...>())
   1478 	: _Inherited(__elements...) { }
   1479 
   1480       template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
   1481 	       _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
   1482 	explicit constexpr
   1483 	tuple(const _Elements&... __elements)
   1484 	noexcept(__nothrow_constructible<const _Elements&...>())
   1485 	: _Inherited(__elements...) { }
   1486 
   1487       template<typename... _UElements,
   1488 	       bool _Valid = __valid_args<_UElements...>(),
   1489 	       _ImplicitCtor<_Valid, _UElements...> = true>
   1490 	constexpr
   1491 	tuple(_UElements&&... __elements)
   1492 	noexcept(__nothrow_constructible<_UElements...>())
   1493 	: _Inherited(std::forward<_UElements>(__elements)...)
   1494 	{ __glibcxx_no_dangling_refs(_UElements&&); }
   1495 
   1496       template<typename... _UElements,
   1497 	       bool _Valid = __valid_args<_UElements...>(),
   1498 	       _ExplicitCtor<_Valid, _UElements...> = false>
   1499 	explicit constexpr
   1500 	tuple(_UElements&&... __elements)
   1501 	noexcept(__nothrow_constructible<_UElements...>())
   1502 	: _Inherited(std::forward<_UElements>(__elements)...)
   1503 	{ __glibcxx_no_dangling_refs(_UElements&&); }
   1504 
   1505       constexpr tuple(const tuple&) = default;
   1506 
   1507       constexpr tuple(tuple&&) = default;
   1508 
   1509       template<typename... _UElements,
   1510 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
   1511 			   && !__use_other_ctor<const tuple<_UElements...>&>(),
   1512 	       _ImplicitCtor<_Valid, const _UElements&...> = true>
   1513 	constexpr
   1514 	tuple(const tuple<_UElements...>& __in)
   1515 	noexcept(__nothrow_constructible<const _UElements&...>())
   1516 	: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
   1517 	{ __glibcxx_no_dangling_refs(const _UElements&); }
   1518 
   1519       template<typename... _UElements,
   1520 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
   1521 			   && !__use_other_ctor<const tuple<_UElements...>&>(),
   1522 	       _ExplicitCtor<_Valid, const _UElements&...> = false>
   1523 	explicit constexpr
   1524 	tuple(const tuple<_UElements...>& __in)
   1525 	noexcept(__nothrow_constructible<const _UElements&...>())
   1526 	: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
   1527 	{ __glibcxx_no_dangling_refs(const _UElements&); }
   1528 
   1529       template<typename... _UElements,
   1530 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
   1531 			     && !__use_other_ctor<tuple<_UElements...>&&>(),
   1532 	       _ImplicitCtor<_Valid, _UElements...> = true>
   1533 	constexpr
   1534 	tuple(tuple<_UElements...>&& __in)
   1535 	noexcept(__nothrow_constructible<_UElements...>())
   1536 	: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
   1537 	{ __glibcxx_no_dangling_refs(_UElements&&); }
   1538 
   1539       template<typename... _UElements,
   1540 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
   1541 			     && !__use_other_ctor<tuple<_UElements...>&&>(),
   1542 	       _ExplicitCtor<_Valid, _UElements...> = false>
   1543 	explicit constexpr
   1544 	tuple(tuple<_UElements...>&& __in)
   1545 	noexcept(__nothrow_constructible<_UElements...>())
   1546 	: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
   1547 	{ __glibcxx_no_dangling_refs(_UElements&&); }
   1548 
   1549       // Allocator-extended constructors.
   1550 
   1551       template<typename _Alloc,
   1552 	       _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
   1553 	_GLIBCXX20_CONSTEXPR
   1554 	tuple(allocator_arg_t __tag, const _Alloc& __a)
   1555 	: _Inherited(__tag, __a) { }
   1556 
   1557       template<typename _Alloc,
   1558 	       _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
   1559 	_GLIBCXX20_CONSTEXPR
   1560 	explicit
   1561 	tuple(allocator_arg_t __tag, const _Alloc& __a)
   1562 	: _Inherited(__tag, __a) { }
   1563 
   1564       template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
   1565 	       _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
   1566 	_GLIBCXX20_CONSTEXPR
   1567 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1568 	      const _Elements&... __elements)
   1569 	: _Inherited(__tag, __a, __elements...) { }
   1570 
   1571       template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
   1572 	       _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
   1573 	_GLIBCXX20_CONSTEXPR
   1574 	explicit
   1575 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1576 	      const _Elements&... __elements)
   1577 	: _Inherited(__tag, __a, __elements...) { }
   1578 
   1579       template<typename _Alloc, typename... _UElements,
   1580 	       bool _Valid = __valid_args<_UElements...>(),
   1581 	       _ImplicitCtor<_Valid, _UElements...> = true>
   1582 	_GLIBCXX20_CONSTEXPR
   1583 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1584 	      _UElements&&... __elements)
   1585 	: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
   1586 	{ __glibcxx_no_dangling_refs(_UElements&&); }
   1587 
   1588       template<typename _Alloc, typename... _UElements,
   1589 		 bool _Valid = __valid_args<_UElements...>(),
   1590 	       _ExplicitCtor<_Valid, _UElements...> = false>
   1591 	_GLIBCXX20_CONSTEXPR
   1592 	explicit
   1593 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1594 	      _UElements&&... __elements)
   1595 	: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
   1596 	{ __glibcxx_no_dangling_refs(_UElements&&); }
   1597 
   1598       template<typename _Alloc>
   1599 	_GLIBCXX20_CONSTEXPR
   1600 	tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
   1601 	: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
   1602 
   1603       template<typename _Alloc>
   1604 	_GLIBCXX20_CONSTEXPR
   1605 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
   1606 	: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
   1607 
   1608       template<typename _Alloc, typename... _UElements,
   1609 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
   1610 			     && !__use_other_ctor<const tuple<_UElements...>&>(),
   1611 	       _ImplicitCtor<_Valid, const _UElements&...> = true>
   1612 	_GLIBCXX20_CONSTEXPR
   1613 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1614 	      const tuple<_UElements...>& __in)
   1615 	: _Inherited(__tag, __a,
   1616 		     static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
   1617 	{ __glibcxx_no_dangling_refs(const _UElements&); }
   1618 
   1619       template<typename _Alloc, typename... _UElements,
   1620 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
   1621 			     && !__use_other_ctor<const tuple<_UElements...>&>(),
   1622 	       _ExplicitCtor<_Valid, const _UElements&...> = false>
   1623 	_GLIBCXX20_CONSTEXPR
   1624 	explicit
   1625 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1626 	      const tuple<_UElements...>& __in)
   1627 	: _Inherited(__tag, __a,
   1628 		     static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
   1629 	{ __glibcxx_no_dangling_refs(const _UElements&); }
   1630 
   1631       template<typename _Alloc, typename... _UElements,
   1632 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
   1633 			     && !__use_other_ctor<tuple<_UElements...>&&>(),
   1634 	       _ImplicitCtor<_Valid, _UElements...> = true>
   1635 	_GLIBCXX20_CONSTEXPR
   1636 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1637 	      tuple<_UElements...>&& __in)
   1638 	: _Inherited(__tag, __a,
   1639 		     static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
   1640 	{ __glibcxx_no_dangling_refs(_UElements&&); }
   1641 
   1642       template<typename _Alloc, typename... _UElements,
   1643 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
   1644 			     && !__use_other_ctor<tuple<_UElements...>&&>(),
   1645 	       _ExplicitCtor<_Valid, _UElements...> = false>
   1646 	_GLIBCXX20_CONSTEXPR
   1647 	explicit
   1648 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1649 	      tuple<_UElements...>&& __in)
   1650 	: _Inherited(__tag, __a,
   1651 		     static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
   1652 	{ __glibcxx_no_dangling_refs(_UElements&&); }
   1653 #endif // concepts && conditional_explicit
   1654 
   1655       // tuple assignment
   1656 
   1657 #if __cpp_concepts && __cpp_consteval // >= C++20
   1658     private:
   1659       template<typename... _UTypes>
   1660 	static consteval bool
   1661 	__assignable()
   1662 	{
   1663 	  if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
   1664 	    return __and_v<is_assignable<_Elements&, _UTypes>...>;
   1665 	  else
   1666 	    return false;
   1667 	}
   1668 
   1669       template<typename... _UTypes>
   1670 	static consteval bool
   1671 	__nothrow_assignable()
   1672 	{
   1673 	  if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
   1674 	    return __and_v<is_nothrow_assignable<_Elements&, _UTypes>...>;
   1675 	  else
   1676 	    return false;
   1677 	}
   1678 
   1679 #if __cpp_lib_ranges_zip // >= C++23
   1680       template<typename... _UTypes>
   1681 	static consteval bool
   1682 	__const_assignable()
   1683 	{
   1684 	  if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
   1685 	    return __and_v<is_assignable<const _Elements&, _UTypes>...>;
   1686 	  else
   1687 	    return false;
   1688 	}
   1689 #endif // C++23
   1690 
   1691 #if __cpp_lib_tuple_like // >= C++23
   1692       template<typename _UTuple>
   1693 	static consteval bool
   1694 	__assignable_from_tuple_like()
   1695 	{
   1696 	  return []<size_t... _Is>(index_sequence<_Is...>) {
   1697 	    return __assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
   1698 	  }(index_sequence_for<_Elements...>{});
   1699 	}
   1700 
   1701       template<typename _UTuple>
   1702 	static consteval bool
   1703 	__const_assignable_from_tuple_like()
   1704 	{
   1705 	  return []<size_t... _Is>(index_sequence<_Is...>) {
   1706 	    return __const_assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
   1707 	  }(index_sequence_for<_Elements...>{});
   1708 	}
   1709 #endif // C++23
   1710 
   1711     public:
   1712 
   1713       tuple& operator=(const tuple& __u) = delete;
   1714 
   1715       constexpr tuple&
   1716       operator=(const tuple& __u)
   1717       noexcept(__nothrow_assignable<const _Elements&...>())
   1718       requires (__assignable<const _Elements&...>())
   1719       {
   1720 	this->_M_assign(__u);
   1721 	return *this;
   1722       }
   1723 
   1724       constexpr tuple&
   1725       operator=(tuple&& __u)
   1726       noexcept(__nothrow_assignable<_Elements...>())
   1727       requires (__assignable<_Elements...>())
   1728       {
   1729 	this->_M_assign(std::move(__u));
   1730 	return *this;
   1731       }
   1732 
   1733       template<typename... _UTypes>
   1734 	requires (__assignable<const _UTypes&...>())
   1735 	constexpr tuple&
   1736 	operator=(const tuple<_UTypes...>& __u)
   1737 	noexcept(__nothrow_assignable<const _UTypes&...>())
   1738 	{
   1739 	  this->_M_assign(__u);
   1740 	  return *this;
   1741 	}
   1742 
   1743       template<typename... _UTypes>
   1744 	requires (__assignable<_UTypes...>())
   1745 	constexpr tuple&
   1746 	operator=(tuple<_UTypes...>&& __u)
   1747 	noexcept(__nothrow_assignable<_UTypes...>())
   1748 	{
   1749 	  this->_M_assign(std::move(__u));
   1750 	  return *this;
   1751 	}
   1752 
   1753 #if __cpp_lib_ranges_zip // >= C++23
   1754       constexpr const tuple&
   1755       operator=(const tuple& __u) const
   1756       requires (__const_assignable<const _Elements&...>())
   1757       {
   1758 	this->_M_assign(__u);
   1759 	return *this;
   1760       }
   1761 
   1762       constexpr const tuple&
   1763       operator=(tuple&& __u) const
   1764       requires (__const_assignable<_Elements...>())
   1765       {
   1766 	this->_M_assign(std::move(__u));
   1767 	return *this;
   1768       }
   1769 
   1770       template<typename... _UTypes>
   1771 	constexpr const tuple&
   1772 	operator=(const tuple<_UTypes...>& __u) const
   1773 	requires (__const_assignable<const _UTypes&...>())
   1774 	{
   1775 	  this->_M_assign(__u);
   1776 	  return *this;
   1777 	}
   1778 
   1779       template<typename... _UTypes>
   1780 	constexpr const tuple&
   1781 	operator=(tuple<_UTypes...>&& __u) const
   1782 	requires (__const_assignable<_UTypes...>())
   1783 	{
   1784 	  this->_M_assign(std::move(__u));
   1785 	  return *this;
   1786 	}
   1787 #endif // C++23
   1788 
   1789       template<typename _U1, typename _U2>
   1790 	requires (__assignable<const _U1&, const _U2&>())
   1791 	constexpr tuple&
   1792 	operator=(const pair<_U1, _U2>& __u)
   1793 	noexcept(__nothrow_assignable<const _U1&, const _U2&>())
   1794 	{
   1795 	  this->_M_head(*this) = __u.first;
   1796 	  this->_M_tail(*this)._M_head(*this) = __u.second;
   1797 	  return *this;
   1798 	}
   1799 
   1800       template<typename _U1, typename _U2>
   1801 	requires (__assignable<_U1, _U2>())
   1802 	constexpr tuple&
   1803 	operator=(pair<_U1, _U2>&& __u)
   1804 	noexcept(__nothrow_assignable<_U1, _U2>())
   1805 	{
   1806 	  this->_M_head(*this) = std::forward<_U1>(__u.first);
   1807 	  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
   1808 	  return *this;
   1809 	}
   1810 
   1811 #if __cpp_lib_ranges_zip // >= C++23
   1812       template<typename _U1, typename _U2>
   1813 	requires (__const_assignable<const _U1&, const _U2>())
   1814 	constexpr const tuple&
   1815 	operator=(const pair<_U1, _U2>& __u) const
   1816 	{
   1817 	  this->_M_head(*this) = __u.first;
   1818 	  this->_M_tail(*this)._M_head(*this) = __u.second;
   1819 	  return *this;
   1820 	}
   1821 
   1822       template<typename _U1, typename _U2>
   1823 	requires (__const_assignable<_U1, _U2>())
   1824 	constexpr const tuple&
   1825 	operator=(pair<_U1, _U2>&& __u) const
   1826 	{
   1827 	  this->_M_head(*this) = std::forward<_U1>(__u.first);
   1828 	  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
   1829 	  return *this;
   1830 	}
   1831 #endif // C++23
   1832 
   1833 #if __cpp_lib_tuple_like // >= C++23
   1834       template<__eligible_tuple_like<tuple> _UTuple>
   1835 	requires (__assignable_from_tuple_like<_UTuple>())
   1836 	constexpr tuple&
   1837 	operator=(_UTuple&& __u)
   1838 	{
   1839 	  this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
   1840 	  return *this;
   1841 	}
   1842 
   1843       template<__eligible_tuple_like<tuple> _UTuple>
   1844 	requires (__const_assignable_from_tuple_like<_UTuple>())
   1845 	constexpr const tuple&
   1846 	operator=(_UTuple&& __u) const
   1847 	{
   1848 	  this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
   1849 	  return *this;
   1850 	}
   1851 
   1852       template<__tuple_like _UTuple>
   1853 	requires (!__is_tuple_v<_UTuple>)
   1854 	friend constexpr bool
   1855 	operator==(const tuple& __t, const _UTuple& __u)
   1856 	{
   1857 	  static_assert(sizeof...(_Elements) == tuple_size_v<_UTuple>,
   1858 	      "tuple objects can only be compared if they have equal sizes.");
   1859 	  return [&]<size_t... _Is>(index_sequence<_Is...>) {
   1860 	    return (bool(std::get<_Is>(__t) == std::get<_Is>(__u))
   1861 		    && ...);
   1862 	  }(index_sequence_for<_Elements...>{});
   1863 	}
   1864 
   1865       template<__tuple_like _UTuple,
   1866 	       typename = make_index_sequence<tuple_size_v<_UTuple>>>
   1867 	struct __tuple_like_common_comparison_category;
   1868 
   1869       template<__tuple_like _UTuple, size_t... _Is>
   1870 	requires requires
   1871 	  { typename void_t<__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>; }
   1872 	struct __tuple_like_common_comparison_category<_UTuple, index_sequence<_Is...>>
   1873 	{
   1874 	  using type = common_comparison_category_t
   1875 	    <__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>;
   1876 	};
   1877 
   1878       template<__tuple_like _UTuple>
   1879 	requires (!__is_tuple_v<_UTuple>)
   1880 	friend constexpr typename __tuple_like_common_comparison_category<_UTuple>::type
   1881 	operator<=>(const tuple& __t, const _UTuple& __u)
   1882 	{
   1883 	  using _Cat = typename __tuple_like_common_comparison_category<_UTuple>::type;
   1884 	  return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Elements...>());
   1885 	}
   1886 #endif // C++23
   1887 
   1888 #else // ! (concepts && consteval)
   1889 
   1890     private:
   1891       template<typename... _UElements>
   1892 	static constexpr
   1893 	__enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
   1894 	__assignable()
   1895 	{ return __and_<is_assignable<_Elements&, _UElements>...>::value; }
   1896 
   1897       // Condition for noexcept-specifier of an assignment operator.
   1898       template<typename... _UElements>
   1899 	static constexpr bool __nothrow_assignable()
   1900 	{
   1901 	  return
   1902 	    __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
   1903 	}
   1904 
   1905     public:
   1906 
   1907       _GLIBCXX20_CONSTEXPR
   1908       tuple&
   1909       operator=(__conditional_t<__assignable<const _Elements&...>(),
   1910 				const tuple&,
   1911 				const __nonesuch&> __in)
   1912       noexcept(__nothrow_assignable<const _Elements&...>())
   1913       {
   1914 	this->_M_assign(__in);
   1915 	return *this;
   1916       }
   1917 
   1918       _GLIBCXX20_CONSTEXPR
   1919       tuple&
   1920       operator=(__conditional_t<__assignable<_Elements...>(),
   1921 				tuple&&,
   1922 				__nonesuch&&> __in)
   1923       noexcept(__nothrow_assignable<_Elements...>())
   1924       {
   1925 	this->_M_assign(std::move(__in));
   1926 	return *this;
   1927       }
   1928 
   1929       template<typename... _UElements>
   1930 	_GLIBCXX20_CONSTEXPR
   1931 	__enable_if_t<__assignable<const _UElements&...>(), tuple&>
   1932 	operator=(const tuple<_UElements...>& __in)
   1933 	noexcept(__nothrow_assignable<const _UElements&...>())
   1934 	{
   1935 	  this->_M_assign(__in);
   1936 	  return *this;
   1937 	}
   1938 
   1939       template<typename... _UElements>
   1940 	_GLIBCXX20_CONSTEXPR
   1941 	__enable_if_t<__assignable<_UElements...>(), tuple&>
   1942 	operator=(tuple<_UElements...>&& __in)
   1943 	noexcept(__nothrow_assignable<_UElements...>())
   1944 	{
   1945 	  this->_M_assign(std::move(__in));
   1946 	  return *this;
   1947 	}
   1948 #endif // concepts && consteval
   1949 
   1950       // tuple swap
   1951       _GLIBCXX20_CONSTEXPR
   1952       void
   1953       swap(tuple& __in)
   1954       noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
   1955       { _Inherited::_M_swap(__in); }
   1956 
   1957 #if __cpp_lib_ranges_zip // >= C++23
   1958       // As an extension, we constrain the const swap member function in order
   1959       // to continue accepting explicit instantiation of tuples whose elements
   1960       // are not all const swappable.  Without this constraint, such an
   1961       // explicit instantiation would also instantiate the ill-formed body of
   1962       // this function and yield a hard error.  This constraint shouldn't
   1963       // affect the behavior of valid programs.
   1964       constexpr void
   1965       swap(const tuple& __in) const
   1966       noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
   1967       requires (is_swappable_v<const _Elements> && ...)
   1968       { _Inherited::_M_swap(__in); }
   1969 #endif // C++23
   1970     };
   1971 
   1972 #if __cpp_deduction_guides >= 201606
   1973   template<typename... _UTypes>
   1974     tuple(_UTypes...) -> tuple<_UTypes...>;
   1975   template<typename _T1, typename _T2>
   1976     tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
   1977   template<typename _Alloc, typename... _UTypes>
   1978     tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
   1979   template<typename _Alloc, typename _T1, typename _T2>
   1980     tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
   1981   template<typename _Alloc, typename... _UTypes>
   1982     tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
   1983 #endif
   1984 
   1985   // Explicit specialization, zero-element tuple.
   1986   template<>
   1987     class tuple<>
   1988     {
   1989     public:
   1990       _GLIBCXX20_CONSTEXPR
   1991       void swap(tuple&) noexcept { /* no-op */ }
   1992 #if __cpp_lib_ranges_zip // >= C++23
   1993       constexpr void swap(const tuple&) const noexcept { /* no-op */ }
   1994 #endif
   1995       // We need the default since we're going to define no-op
   1996       // allocator constructors.
   1997       tuple() = default;
   1998       // No-op allocator constructors.
   1999       template<typename _Alloc>
   2000 	_GLIBCXX20_CONSTEXPR
   2001 	tuple(allocator_arg_t, const _Alloc&) noexcept { }
   2002       template<typename _Alloc>
   2003 	_GLIBCXX20_CONSTEXPR
   2004 	tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
   2005     };
   2006 
   2007 #if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
   2008   /// Partial specialization, 2-element tuple.
   2009   /// Includes construction and assignment from a pair.
   2010   template<typename _T1, typename _T2>
   2011     class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
   2012     {
   2013       typedef _Tuple_impl<0, _T1, _T2> _Inherited;
   2014 
   2015       // Constraint for non-explicit default constructor
   2016       template<bool _Dummy, typename _U1, typename _U2>
   2017 	using _ImplicitDefaultCtor = __enable_if_t<
   2018 	  _TupleConstraints<_Dummy, _U1, _U2>::
   2019 	    __is_implicitly_default_constructible(),
   2020 	  bool>;
   2021 
   2022       // Constraint for explicit default constructor
   2023       template<bool _Dummy, typename _U1, typename _U2>
   2024 	using _ExplicitDefaultCtor = __enable_if_t<
   2025 	  _TupleConstraints<_Dummy, _U1, _U2>::
   2026 	    __is_explicitly_default_constructible(),
   2027 	  bool>;
   2028 
   2029       template<bool _Dummy>
   2030 	using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
   2031 
   2032       // Constraint for non-explicit constructors
   2033       template<bool _Cond, typename _U1, typename _U2>
   2034 	using _ImplicitCtor = __enable_if_t<
   2035 	  _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
   2036 	  bool>;
   2037 
   2038       // Constraint for non-explicit constructors
   2039       template<bool _Cond, typename _U1, typename _U2>
   2040 	using _ExplicitCtor = __enable_if_t<
   2041 	  _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
   2042 	  bool>;
   2043 
   2044       template<typename _U1, typename _U2>
   2045 	static constexpr bool __assignable()
   2046 	{
   2047 	  return __and_<is_assignable<_T1&, _U1>,
   2048 			is_assignable<_T2&, _U2>>::value;
   2049 	}
   2050 
   2051       template<typename _U1, typename _U2>
   2052 	static constexpr bool __nothrow_assignable()
   2053 	{
   2054 	  return __and_<is_nothrow_assignable<_T1&, _U1>,
   2055 			is_nothrow_assignable<_T2&, _U2>>::value;
   2056 	}
   2057 
   2058       template<typename _U1, typename _U2>
   2059 	static constexpr bool __nothrow_constructible()
   2060 	{
   2061 	  return __and_<is_nothrow_constructible<_T1, _U1>,
   2062 			    is_nothrow_constructible<_T2, _U2>>::value;
   2063 	}
   2064 
   2065       static constexpr bool __nothrow_default_constructible()
   2066       {
   2067 	return __and_<is_nothrow_default_constructible<_T1>,
   2068 		      is_nothrow_default_constructible<_T2>>::value;
   2069       }
   2070 
   2071       template<typename _U1>
   2072 	static constexpr bool __is_alloc_arg()
   2073 	{ return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
   2074 
   2075       /// @cond undocumented
   2076 #undef __glibcxx_no_dangling_refs
   2077       // Error if construction from _U1 and _U2 would create a dangling ref.
   2078 #if __has_builtin(__reference_constructs_from_temporary) \
   2079       && defined _GLIBCXX_DEBUG
   2080 # define __glibcxx_no_dangling_refs(_U1, _U2) \
   2081   static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
   2082 	       && !__reference_constructs_from_temporary(_T2, _U2), \
   2083 		"std::tuple constructor creates a dangling reference")
   2084 #else
   2085 # define __glibcxx_no_dangling_refs(_U1, _U2)
   2086 #endif
   2087       /// @endcond
   2088 
   2089     public:
   2090       template<bool _Dummy = true,
   2091 	       _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
   2092 	constexpr
   2093 	tuple()
   2094 	noexcept(__nothrow_default_constructible())
   2095 	: _Inherited() { }
   2096 
   2097       template<bool _Dummy = true,
   2098 	       _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
   2099 	explicit constexpr
   2100 	tuple()
   2101 	noexcept(__nothrow_default_constructible())
   2102 	: _Inherited() { }
   2103 
   2104       template<bool _Dummy = true,
   2105 	       _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
   2106 	constexpr
   2107 	tuple(const _T1& __a1, const _T2& __a2)
   2108 	noexcept(__nothrow_constructible<const _T1&, const _T2&>())
   2109 	: _Inherited(__a1, __a2) { }
   2110 
   2111       template<bool _Dummy = true,
   2112 	       _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
   2113 	explicit constexpr
   2114 	tuple(const _T1& __a1, const _T2& __a2)
   2115 	noexcept(__nothrow_constructible<const _T1&, const _T2&>())
   2116 	: _Inherited(__a1, __a2) { }
   2117 
   2118       template<typename _U1, typename _U2,
   2119 	       _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
   2120 	constexpr
   2121 	tuple(_U1&& __a1, _U2&& __a2)
   2122 	noexcept(__nothrow_constructible<_U1, _U2>())
   2123 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
   2124 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2125 
   2126       template<typename _U1, typename _U2,
   2127 	       _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
   2128 	explicit constexpr
   2129 	tuple(_U1&& __a1, _U2&& __a2)
   2130 	noexcept(__nothrow_constructible<_U1, _U2>())
   2131 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
   2132 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2133 
   2134       constexpr tuple(const tuple&) = default;
   2135 
   2136       constexpr tuple(tuple&&) = default;
   2137 
   2138       template<typename _U1, typename _U2,
   2139 	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
   2140 	constexpr
   2141 	tuple(const tuple<_U1, _U2>& __in)
   2142 	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
   2143 	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
   2144 	{ __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
   2145 
   2146       template<typename _U1, typename _U2,
   2147 	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
   2148 	explicit constexpr
   2149 	tuple(const tuple<_U1, _U2>& __in)
   2150 	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
   2151 	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
   2152 	{ __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
   2153 
   2154       template<typename _U1, typename _U2,
   2155 	       _ImplicitCtor<true, _U1, _U2> = true>
   2156 	constexpr
   2157 	tuple(tuple<_U1, _U2>&& __in)
   2158 	noexcept(__nothrow_constructible<_U1, _U2>())
   2159 	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
   2160 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2161 
   2162       template<typename _U1, typename _U2,
   2163 	       _ExplicitCtor<true, _U1, _U2> = false>
   2164 	explicit constexpr
   2165 	tuple(tuple<_U1, _U2>&& __in)
   2166 	noexcept(__nothrow_constructible<_U1, _U2>())
   2167 	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
   2168 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2169 
   2170       template<typename _U1, typename _U2,
   2171 	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
   2172 	constexpr
   2173 	tuple(const pair<_U1, _U2>& __in)
   2174 	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
   2175 	: _Inherited(__in.first, __in.second)
   2176 	{ __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
   2177 
   2178       template<typename _U1, typename _U2,
   2179 	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
   2180 	explicit constexpr
   2181 	tuple(const pair<_U1, _U2>& __in)
   2182 	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
   2183 	: _Inherited(__in.first, __in.second)
   2184 	{ __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
   2185 
   2186       template<typename _U1, typename _U2,
   2187 	       _ImplicitCtor<true, _U1, _U2> = true>
   2188 	constexpr
   2189 	tuple(pair<_U1, _U2>&& __in)
   2190 	noexcept(__nothrow_constructible<_U1, _U2>())
   2191 	: _Inherited(std::forward<_U1>(__in.first),
   2192 		     std::forward<_U2>(__in.second))
   2193 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2194 
   2195       template<typename _U1, typename _U2,
   2196 	       _ExplicitCtor<true, _U1, _U2> = false>
   2197 	explicit constexpr
   2198 	tuple(pair<_U1, _U2>&& __in)
   2199 	noexcept(__nothrow_constructible<_U1, _U2>())
   2200 	: _Inherited(std::forward<_U1>(__in.first),
   2201 		     std::forward<_U2>(__in.second))
   2202 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2203 
   2204       // Allocator-extended constructors.
   2205 
   2206       template<typename _Alloc,
   2207 	       _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
   2208 	_GLIBCXX20_CONSTEXPR
   2209 	tuple(allocator_arg_t __tag, const _Alloc& __a)
   2210 	: _Inherited(__tag, __a) { }
   2211 
   2212       template<typename _Alloc,
   2213 	       _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
   2214 	_GLIBCXX20_CONSTEXPR
   2215 	explicit
   2216 	tuple(allocator_arg_t __tag, const _Alloc& __a)
   2217 	: _Inherited(__tag, __a) { }
   2218 
   2219       template<typename _Alloc, bool _Dummy = true,
   2220 	       _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
   2221 	_GLIBCXX20_CONSTEXPR
   2222 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   2223 	      const _T1& __a1, const _T2& __a2)
   2224 	: _Inherited(__tag, __a, __a1, __a2) { }
   2225 
   2226       template<typename _Alloc, bool _Dummy = true,
   2227 	       _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
   2228 	explicit
   2229 	_GLIBCXX20_CONSTEXPR
   2230 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   2231 	      const _T1& __a1, const _T2& __a2)
   2232 	: _Inherited(__tag, __a, __a1, __a2) { }
   2233 
   2234       template<typename _Alloc, typename _U1, typename _U2,
   2235 	       _ImplicitCtor<true, _U1, _U2> = true>
   2236 	_GLIBCXX20_CONSTEXPR
   2237 	tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
   2238 	: _Inherited(__tag, __a, std::forward<_U1>(__a1),
   2239 		     std::forward<_U2>(__a2))
   2240 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2241 
   2242       template<typename _Alloc, typename _U1, typename _U2,
   2243 	       _ExplicitCtor<true, _U1, _U2> = false>
   2244 	explicit
   2245 	_GLIBCXX20_CONSTEXPR
   2246 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   2247 	      _U1&& __a1, _U2&& __a2)
   2248 	: _Inherited(__tag, __a, std::forward<_U1>(__a1),
   2249 		     std::forward<_U2>(__a2))
   2250 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2251 
   2252       template<typename _Alloc>
   2253 	_GLIBCXX20_CONSTEXPR
   2254 	tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
   2255 	: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
   2256 
   2257       template<typename _Alloc>
   2258 	_GLIBCXX20_CONSTEXPR
   2259 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
   2260 	: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
   2261 
   2262       template<typename _Alloc, typename _U1, typename _U2,
   2263 	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
   2264 	_GLIBCXX20_CONSTEXPR
   2265 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   2266 	      const tuple<_U1, _U2>& __in)
   2267 	: _Inherited(__tag, __a,
   2268 		     static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
   2269 	{ __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
   2270 
   2271       template<typename _Alloc, typename _U1, typename _U2,
   2272 	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
   2273 	explicit
   2274 	_GLIBCXX20_CONSTEXPR
   2275 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   2276 	      const tuple<_U1, _U2>& __in)
   2277 	: _Inherited(__tag, __a,
   2278 		     static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
   2279 	{ __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
   2280 
   2281       template<typename _Alloc, typename _U1, typename _U2,
   2282 	       _ImplicitCtor<true, _U1, _U2> = true>
   2283 	_GLIBCXX20_CONSTEXPR
   2284 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
   2285 	: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
   2286 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2287 
   2288       template<typename _Alloc, typename _U1, typename _U2,
   2289 	       _ExplicitCtor<true, _U1, _U2> = false>
   2290 	explicit
   2291 	_GLIBCXX20_CONSTEXPR
   2292 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
   2293 	: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
   2294 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2295 
   2296       template<typename _Alloc, typename _U1, typename _U2,
   2297 	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
   2298 	_GLIBCXX20_CONSTEXPR
   2299 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   2300 	      const pair<_U1, _U2>& __in)
   2301 	: _Inherited(__tag, __a, __in.first, __in.second)
   2302 	{ __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
   2303 
   2304       template<typename _Alloc, typename _U1, typename _U2,
   2305 	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
   2306 	explicit
   2307 	_GLIBCXX20_CONSTEXPR
   2308 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   2309 	      const pair<_U1, _U2>& __in)
   2310 	: _Inherited(__tag, __a, __in.first, __in.second)
   2311 	{ __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
   2312 
   2313       template<typename _Alloc, typename _U1, typename _U2,
   2314 	       _ImplicitCtor<true, _U1, _U2> = true>
   2315 	_GLIBCXX20_CONSTEXPR
   2316 	tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
   2317 	: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
   2318 		     std::forward<_U2>(__in.second))
   2319 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2320 
   2321       template<typename _Alloc, typename _U1, typename _U2,
   2322 	       _ExplicitCtor<true, _U1, _U2> = false>
   2323 	explicit
   2324 	_GLIBCXX20_CONSTEXPR
   2325 	tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
   2326 	: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
   2327 		     std::forward<_U2>(__in.second))
   2328 	{ __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
   2329 
   2330       // Tuple assignment.
   2331 
   2332       _GLIBCXX20_CONSTEXPR
   2333       tuple&
   2334       operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
   2335 				const tuple&,
   2336 				const __nonesuch&> __in)
   2337       noexcept(__nothrow_assignable<const _T1&, const _T2&>())
   2338       {
   2339 	this->_M_assign(__in);
   2340 	return *this;
   2341       }
   2342 
   2343       _GLIBCXX20_CONSTEXPR
   2344       tuple&
   2345       operator=(__conditional_t<__assignable<_T1, _T2>(),
   2346 				tuple&&,
   2347 				__nonesuch&&> __in)
   2348       noexcept(__nothrow_assignable<_T1, _T2>())
   2349       {
   2350 	this->_M_assign(std::move(__in));
   2351 	return *this;
   2352       }
   2353 
   2354       template<typename _U1, typename _U2>
   2355 	_GLIBCXX20_CONSTEXPR
   2356 	__enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
   2357 	operator=(const tuple<_U1, _U2>& __in)
   2358 	noexcept(__nothrow_assignable<const _U1&, const _U2&>())
   2359 	{
   2360 	  this->_M_assign(__in);
   2361 	  return *this;
   2362 	}
   2363 
   2364       template<typename _U1, typename _U2>
   2365 	_GLIBCXX20_CONSTEXPR
   2366 	__enable_if_t<__assignable<_U1, _U2>(), tuple&>
   2367 	operator=(tuple<_U1, _U2>&& __in)
   2368 	noexcept(__nothrow_assignable<_U1, _U2>())
   2369 	{
   2370 	  this->_M_assign(std::move(__in));
   2371 	  return *this;
   2372 	}
   2373 
   2374       template<typename _U1, typename _U2>
   2375 	_GLIBCXX20_CONSTEXPR
   2376 	__enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
   2377 	operator=(const pair<_U1, _U2>& __in)
   2378 	noexcept(__nothrow_assignable<const _U1&, const _U2&>())
   2379 	{
   2380 	  this->_M_head(*this) = __in.first;
   2381 	  this->_M_tail(*this)._M_head(*this) = __in.second;
   2382 	  return *this;
   2383 	}
   2384 
   2385       template<typename _U1, typename _U2>
   2386 	_GLIBCXX20_CONSTEXPR
   2387 	__enable_if_t<__assignable<_U1, _U2>(), tuple&>
   2388 	operator=(pair<_U1, _U2>&& __in)
   2389 	noexcept(__nothrow_assignable<_U1, _U2>())
   2390 	{
   2391 	  this->_M_head(*this) = std::forward<_U1>(__in.first);
   2392 	  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
   2393 	  return *this;
   2394 	}
   2395 
   2396       _GLIBCXX20_CONSTEXPR
   2397       void
   2398       swap(tuple& __in)
   2399       noexcept(__and_<__is_nothrow_swappable<_T1>,
   2400 		      __is_nothrow_swappable<_T2>>::value)
   2401       { _Inherited::_M_swap(__in); }
   2402     };
   2403 #endif // concepts && conditional_explicit
   2404 
   2405   /// class tuple_size
   2406   template<typename... _Elements>
   2407     struct tuple_size<tuple<_Elements...>>
   2408     : public integral_constant<size_t, sizeof...(_Elements)> { };
   2409 
   2410 #if __cplusplus >= 201703L
   2411   template<typename... _Types>
   2412     inline constexpr size_t tuple_size_v<tuple<_Types...>>
   2413       = sizeof...(_Types);
   2414 
   2415   template<typename... _Types>
   2416     inline constexpr size_t tuple_size_v<const tuple<_Types...>>
   2417       = sizeof...(_Types);
   2418 #endif
   2419 
   2420   /// Trait to get the Ith element type from a tuple.
   2421   template<size_t __i, typename... _Types>
   2422     struct tuple_element<__i, tuple<_Types...>>
   2423     {
   2424       static_assert(__i < sizeof...(_Types), "tuple index must be in range");
   2425 
   2426       using type = typename _Nth_type<__i, _Types...>::type;
   2427     };
   2428 
   2429   template<size_t __i, typename _Head, typename... _Tail>
   2430     constexpr _Head&
   2431     __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
   2432     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
   2433 
   2434   template<size_t __i, typename _Head, typename... _Tail>
   2435     constexpr const _Head&
   2436     __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
   2437     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
   2438 
   2439   // Deleted overload to improve diagnostics for invalid indices
   2440   template<size_t __i, typename... _Types>
   2441     __enable_if_t<(__i >= sizeof...(_Types))>
   2442     __get_helper(const tuple<_Types...>&) = delete;
   2443 
   2444   /// Return a reference to the ith element of a tuple.
   2445   template<size_t __i, typename... _Elements>
   2446     constexpr __tuple_element_t<__i, tuple<_Elements...>>&
   2447     get(tuple<_Elements...>& __t) noexcept
   2448     { return std::__get_helper<__i>(__t); }
   2449 
   2450   /// Return a const reference to the ith element of a const tuple.
   2451   template<size_t __i, typename... _Elements>
   2452     constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
   2453     get(const tuple<_Elements...>& __t) noexcept
   2454     { return std::__get_helper<__i>(__t); }
   2455 
   2456   /// Return an rvalue reference to the ith element of a tuple rvalue.
   2457   template<size_t __i, typename... _Elements>
   2458     constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
   2459     get(tuple<_Elements...>&& __t) noexcept
   2460     {
   2461       typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
   2462       return std::forward<__element_type>(std::__get_helper<__i>(__t));
   2463     }
   2464 
   2465   /// Return a const rvalue reference to the ith element of a const tuple rvalue.
   2466   template<size_t __i, typename... _Elements>
   2467     constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
   2468     get(const tuple<_Elements...>&& __t) noexcept
   2469     {
   2470       typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
   2471       return std::forward<const __element_type>(std::__get_helper<__i>(__t));
   2472     }
   2473 
   2474   /// @cond undocumented
   2475   // Deleted overload chosen for invalid indices.
   2476   template<size_t __i, typename... _Elements>
   2477     constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
   2478     get(const tuple<_Elements...>&) = delete;
   2479   /// @endcond
   2480 
   2481 #ifdef __cpp_lib_tuples_by_type // C++ >= 14
   2482   /// Return a reference to the unique element of type _Tp of a tuple.
   2483   template <typename _Tp, typename... _Types>
   2484     constexpr _Tp&
   2485     get(tuple<_Types...>& __t) noexcept
   2486     {
   2487       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
   2488       static_assert(__idx < sizeof...(_Types),
   2489 	  "the type T in std::get<T> must occur exactly once in the tuple");
   2490       return std::__get_helper<__idx>(__t);
   2491     }
   2492 
   2493   /// Return a reference to the unique element of type _Tp of a tuple rvalue.
   2494   template <typename _Tp, typename... _Types>
   2495     constexpr _Tp&&
   2496     get(tuple<_Types...>&& __t) noexcept
   2497     {
   2498       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
   2499       static_assert(__idx < sizeof...(_Types),
   2500 	  "the type T in std::get<T> must occur exactly once in the tuple");
   2501       return std::forward<_Tp>(std::__get_helper<__idx>(__t));
   2502     }
   2503 
   2504   /// Return a const reference to the unique element of type _Tp of a tuple.
   2505   template <typename _Tp, typename... _Types>
   2506     constexpr const _Tp&
   2507     get(const tuple<_Types...>& __t) noexcept
   2508     {
   2509       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
   2510       static_assert(__idx < sizeof...(_Types),
   2511 	  "the type T in std::get<T> must occur exactly once in the tuple");
   2512       return std::__get_helper<__idx>(__t);
   2513     }
   2514 
   2515   /// Return a const reference to the unique element of type _Tp of
   2516   /// a const tuple rvalue.
   2517   template <typename _Tp, typename... _Types>
   2518     constexpr const _Tp&&
   2519     get(const tuple<_Types...>&& __t) noexcept
   2520     {
   2521       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
   2522       static_assert(__idx < sizeof...(_Types),
   2523 	  "the type T in std::get<T> must occur exactly once in the tuple");
   2524       return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
   2525     }
   2526 #endif
   2527 
   2528   // This class performs the comparison operations on tuples
   2529   template<typename _Tp, typename _Up, size_t __i, size_t __size>
   2530     struct __tuple_compare
   2531     {
   2532       static constexpr bool
   2533       __eq(const _Tp& __t, const _Up& __u)
   2534       {
   2535 	return bool(std::get<__i>(__t) == std::get<__i>(__u))
   2536 	  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
   2537       }
   2538 
   2539       static constexpr bool
   2540       __less(const _Tp& __t, const _Up& __u)
   2541       {
   2542 	return bool(std::get<__i>(__t) < std::get<__i>(__u))
   2543 	  || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
   2544 	      && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
   2545       }
   2546     };
   2547 
   2548   template<typename _Tp, typename _Up, size_t __size>
   2549     struct __tuple_compare<_Tp, _Up, __size, __size>
   2550     {
   2551       static constexpr bool
   2552       __eq(const _Tp&, const _Up&) { return true; }
   2553 
   2554       static constexpr bool
   2555       __less(const _Tp&, const _Up&) { return false; }
   2556     };
   2557 
   2558   template<typename... _TElements, typename... _UElements>
   2559     constexpr bool
   2560     operator==(const tuple<_TElements...>& __t,
   2561 	       const tuple<_UElements...>& __u)
   2562     {
   2563       static_assert(sizeof...(_TElements) == sizeof...(_UElements),
   2564 	  "tuple objects can only be compared if they have equal sizes.");
   2565       using __compare = __tuple_compare<tuple<_TElements...>,
   2566 					tuple<_UElements...>,
   2567 					0, sizeof...(_TElements)>;
   2568       return __compare::__eq(__t, __u);
   2569     }
   2570 
   2571 #if __cpp_lib_three_way_comparison
   2572   template<typename _Cat, typename _Tp, typename _Up>
   2573     constexpr _Cat
   2574     __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
   2575     { return _Cat::equivalent; }
   2576 
   2577   template<typename _Cat, typename _Tp, typename _Up,
   2578 	   size_t _Idx0, size_t... _Idxs>
   2579     constexpr _Cat
   2580     __tuple_cmp(const _Tp& __t, const _Up& __u,
   2581 		index_sequence<_Idx0, _Idxs...>)
   2582     {
   2583       auto __c
   2584 	= __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
   2585       if (__c != 0)
   2586 	return __c;
   2587       return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
   2588     }
   2589 
   2590   template<typename... _Tps, typename... _Ups>
   2591     constexpr
   2592     common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
   2593     operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
   2594     {
   2595       using _Cat
   2596 	= common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
   2597       return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
   2598     }
   2599 #else
   2600   template<typename... _TElements, typename... _UElements>
   2601     constexpr bool
   2602     operator<(const tuple<_TElements...>& __t,
   2603 	      const tuple<_UElements...>& __u)
   2604     {
   2605       static_assert(sizeof...(_TElements) == sizeof...(_UElements),
   2606 	  "tuple objects can only be compared if they have equal sizes.");
   2607       using __compare = __tuple_compare<tuple<_TElements...>,
   2608 					tuple<_UElements...>,
   2609 					0, sizeof...(_TElements)>;
   2610       return __compare::__less(__t, __u);
   2611     }
   2612 
   2613   template<typename... _TElements, typename... _UElements>
   2614     constexpr bool
   2615     operator!=(const tuple<_TElements...>& __t,
   2616 	       const tuple<_UElements...>& __u)
   2617     { return !(__t == __u); }
   2618 
   2619   template<typename... _TElements, typename... _UElements>
   2620     constexpr bool
   2621     operator>(const tuple<_TElements...>& __t,
   2622 	      const tuple<_UElements...>& __u)
   2623     { return __u < __t; }
   2624 
   2625   template<typename... _TElements, typename... _UElements>
   2626     constexpr bool
   2627     operator<=(const tuple<_TElements...>& __t,
   2628 	       const tuple<_UElements...>& __u)
   2629     { return !(__u < __t); }
   2630 
   2631   template<typename... _TElements, typename... _UElements>
   2632     constexpr bool
   2633     operator>=(const tuple<_TElements...>& __t,
   2634 	       const tuple<_UElements...>& __u)
   2635     { return !(__t < __u); }
   2636 #endif // three_way_comparison
   2637 
   2638   // NB: DR 705.
   2639   /// Create a tuple containing copies of the arguments
   2640   template<typename... _Elements>
   2641     constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
   2642     make_tuple(_Elements&&... __args)
   2643     {
   2644       typedef tuple<typename __decay_and_strip<_Elements>::__type...>
   2645 	__result_type;
   2646       return __result_type(std::forward<_Elements>(__args)...);
   2647     }
   2648 
   2649   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   2650   // 2275. Why is forward_as_tuple not constexpr?
   2651   /// Create a tuple of lvalue or rvalue references to the arguments
   2652   template<typename... _Elements>
   2653     constexpr tuple<_Elements&&...>
   2654     forward_as_tuple(_Elements&&... __args) noexcept
   2655     { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
   2656 
   2657   /// @cond undocumented
   2658   template<size_t, typename, typename, size_t>
   2659     struct __make_tuple_impl;
   2660 
   2661   template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
   2662     struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
   2663     : __make_tuple_impl<_Idx + 1,
   2664 			tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
   2665 			_Tuple, _Nm>
   2666     { };
   2667 
   2668   template<size_t _Nm, typename _Tuple, typename... _Tp>
   2669     struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
   2670     {
   2671       typedef tuple<_Tp...> __type;
   2672     };
   2673 
   2674   template<typename _Tuple>
   2675     struct __do_make_tuple
   2676     : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
   2677     { };
   2678 
   2679   // Returns the std::tuple equivalent of a tuple-like type.
   2680   template<typename _Tuple>
   2681     struct __make_tuple
   2682     : public __do_make_tuple<__remove_cvref_t<_Tuple>>
   2683     { };
   2684 
   2685   // Combines several std::tuple's into a single one.
   2686   template<typename...>
   2687     struct __combine_tuples;
   2688 
   2689   template<>
   2690     struct __combine_tuples<>
   2691     {
   2692       typedef tuple<> __type;
   2693     };
   2694 
   2695   template<typename... _Ts>
   2696     struct __combine_tuples<tuple<_Ts...>>
   2697     {
   2698       typedef tuple<_Ts...> __type;
   2699     };
   2700 
   2701   template<typename... _T1s, typename... _T2s, typename... _Rem>
   2702     struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
   2703     {
   2704       typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
   2705 					_Rem...>::__type __type;
   2706     };
   2707 
   2708   // Computes the result type of tuple_cat given a set of tuple-like types.
   2709   template<typename... _Tpls>
   2710     struct __tuple_cat_result
   2711     {
   2712       typedef typename __combine_tuples
   2713         <typename __make_tuple<_Tpls>::__type...>::__type __type;
   2714     };
   2715 
   2716   // Helper to determine the index set for the first tuple-like
   2717   // type of a given set.
   2718   template<typename...>
   2719     struct __make_1st_indices;
   2720 
   2721   template<>
   2722     struct __make_1st_indices<>
   2723     {
   2724       typedef _Index_tuple<> __type;
   2725     };
   2726 
   2727   template<typename _Tp, typename... _Tpls>
   2728     struct __make_1st_indices<_Tp, _Tpls...>
   2729     {
   2730       typedef typename _Build_index_tuple<tuple_size<
   2731 	typename remove_reference<_Tp>::type>::value>::__type __type;
   2732     };
   2733 
   2734   // Performs the actual concatenation by step-wise expanding tuple-like
   2735   // objects into the elements,  which are finally forwarded into the
   2736   // result tuple.
   2737   template<typename _Ret, typename _Indices, typename... _Tpls>
   2738     struct __tuple_concater;
   2739 
   2740   template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
   2741     struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
   2742     {
   2743       template<typename... _Us>
   2744         static constexpr _Ret
   2745         _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
   2746         {
   2747 	  typedef typename __make_1st_indices<_Tpls...>::__type __idx;
   2748 	  typedef __tuple_concater<_Ret, __idx, _Tpls...>      __next;
   2749 	  return __next::_S_do(std::forward<_Tpls>(__tps)...,
   2750 			       std::forward<_Us>(__us)...,
   2751 			       std::get<_Is>(std::forward<_Tp>(__tp))...);
   2752 	}
   2753     };
   2754 
   2755   template<typename _Ret>
   2756     struct __tuple_concater<_Ret, _Index_tuple<>>
   2757     {
   2758       template<typename... _Us>
   2759 	static constexpr _Ret
   2760 	_S_do(_Us&&... __us)
   2761         {
   2762 	  return _Ret(std::forward<_Us>(__us)...);
   2763 	}
   2764     };
   2765 
   2766   template<typename... _Tps>
   2767     struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
   2768     { };
   2769   /// @endcond
   2770 
   2771   /// Create a `tuple` containing all elements from multiple tuple-like objects
   2772 #if __cpp_lib_tuple_like // >= C++23
   2773   template<__tuple_like... _Tpls>
   2774 #else
   2775   template<typename... _Tpls, typename = typename
   2776            enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
   2777 #endif
   2778     constexpr auto
   2779     tuple_cat(_Tpls&&... __tpls)
   2780     -> typename __tuple_cat_result<_Tpls...>::__type
   2781     {
   2782       typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
   2783       typedef typename __make_1st_indices<_Tpls...>::__type __idx;
   2784       typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
   2785       return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
   2786     }
   2787 
   2788   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   2789   // 2301. Why is tie not constexpr?
   2790   /// Return a tuple of lvalue references bound to the arguments
   2791   template<typename... _Elements>
   2792     constexpr tuple<_Elements&...>
   2793     tie(_Elements&... __args) noexcept
   2794     { return tuple<_Elements&...>(__args...); }
   2795 
   2796   /// Exchange the values of two tuples
   2797   template<typename... _Elements>
   2798     _GLIBCXX20_CONSTEXPR
   2799     inline
   2800 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
   2801     // Constrained free swap overload, see p0185r1
   2802     typename enable_if<__and_<__is_swappable<_Elements>...>::value
   2803       >::type
   2804 #else
   2805     void
   2806 #endif
   2807     swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
   2808     noexcept(noexcept(__x.swap(__y)))
   2809     { __x.swap(__y); }
   2810 
   2811 #if __cpp_lib_ranges_zip // >= C++23
   2812   template<typename... _Elements>
   2813     requires (is_swappable_v<const _Elements> && ...)
   2814     constexpr void
   2815     swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
   2816     noexcept(noexcept(__x.swap(__y)))
   2817     { __x.swap(__y); }
   2818 #endif // C++23
   2819 
   2820 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
   2821   /// Exchange the values of two const tuples (if const elements can be swapped)
   2822   template<typename... _Elements>
   2823     _GLIBCXX20_CONSTEXPR
   2824     typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
   2825     swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
   2826 #endif
   2827 
   2828   // A class (and instance) which can be used in 'tie' when an element
   2829   // of a tuple is not required.
   2830   // _GLIBCXX14_CONSTEXPR
   2831   // 2933. PR for LWG 2773 could be clearer
   2832   struct _Swallow_assign
   2833   {
   2834     template<class _Tp>
   2835       _GLIBCXX14_CONSTEXPR const _Swallow_assign&
   2836       operator=(const _Tp&) const
   2837       { return *this; }
   2838   };
   2839 
   2840   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   2841   // 2773. Making std::ignore constexpr
   2842   /** Used with `std::tie` to ignore an element of a tuple
   2843    *
   2844    * When using `std::tie` to assign the elements of a tuple to variables,
   2845    * unwanted elements can be ignored by using `std::ignore`. For example:
   2846    *
   2847    * ```
   2848    * int x, y;
   2849    * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
   2850    * ```
   2851    *
   2852    * This assignment will perform `x=1; std::ignore=2; y=3;` which results
   2853    * in the second element being ignored.
   2854    *
   2855    * @since C++11
   2856    */
   2857   _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
   2858 
   2859   /// Partial specialization for tuples
   2860   template<typename... _Types, typename _Alloc>
   2861     struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
   2862 
   2863   // See stl_pair.h...
   2864   /** "piecewise construction" using a tuple of arguments for each member.
   2865    *
   2866    * @param __first Arguments for the first member of the pair.
   2867    * @param __second Arguments for the second member of the pair.
   2868    *
   2869    * The elements of each tuple will be used as the constructor arguments
   2870    * for the data members of the pair.
   2871   */
   2872   template<class _T1, class _T2>
   2873     template<typename... _Args1, typename... _Args2>
   2874       _GLIBCXX20_CONSTEXPR
   2875       inline
   2876       pair<_T1, _T2>::
   2877       pair(piecewise_construct_t,
   2878 	   tuple<_Args1...> __first, tuple<_Args2...> __second)
   2879       : pair(__first, __second,
   2880 	     typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
   2881 	     typename _Build_index_tuple<sizeof...(_Args2)>::__type())
   2882       { }
   2883 
   2884   template<class _T1, class _T2>
   2885     template<typename... _Args1, size_t... _Indexes1,
   2886 	     typename... _Args2, size_t... _Indexes2>
   2887       _GLIBCXX20_CONSTEXPR inline
   2888       pair<_T1, _T2>::
   2889       pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
   2890 	   _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
   2891       : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
   2892 	second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
   2893       { }
   2894 
   2895 #if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
   2896   // Unpack a std::tuple into a type trait and use its value.
   2897   // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
   2898   // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
   2899   // Otherwise the result is false (because we don't know if std::get throws).
   2900   template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
   2901     inline constexpr bool __unpack_std_tuple = false;
   2902 
   2903   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
   2904     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
   2905       = _Trait<_Tp, _Up...>::value;
   2906 
   2907   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
   2908     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
   2909       = _Trait<_Tp, _Up&...>::value;
   2910 
   2911   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
   2912     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
   2913       = _Trait<_Tp, const _Up...>::value;
   2914 
   2915   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
   2916     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
   2917       = _Trait<_Tp, const _Up&...>::value;
   2918 #endif
   2919 
   2920 #ifdef __cpp_lib_apply // C++ >= 17
   2921   template <typename _Fn, typename _Tuple, size_t... _Idx>
   2922     constexpr decltype(auto)
   2923     __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
   2924     {
   2925       return std::__invoke(std::forward<_Fn>(__f),
   2926 			   std::get<_Idx>(std::forward<_Tuple>(__t))...);
   2927     }
   2928 
   2929 #if __cpp_lib_tuple_like // >= C++23
   2930   template <typename _Fn, __tuple_like _Tuple>
   2931 #else
   2932   template <typename _Fn, typename _Tuple>
   2933 #endif
   2934     constexpr decltype(auto)
   2935     apply(_Fn&& __f, _Tuple&& __t)
   2936     noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
   2937     {
   2938       using _Indices
   2939 	= make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
   2940       return std::__apply_impl(std::forward<_Fn>(__f),
   2941 			       std::forward<_Tuple>(__t),
   2942 			       _Indices{});
   2943     }
   2944 #endif
   2945 
   2946 #ifdef __cpp_lib_make_from_tuple // C++ >= 17
   2947   template <typename _Tp, typename _Tuple, size_t... _Idx>
   2948     constexpr _Tp
   2949     __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
   2950     { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
   2951 
   2952 #if __cpp_lib_tuple_like // >= C++23
   2953   template <typename _Tp, __tuple_like _Tuple>
   2954 #else
   2955   template <typename _Tp, typename _Tuple>
   2956 #endif
   2957     constexpr _Tp
   2958     make_from_tuple(_Tuple&& __t)
   2959     noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
   2960     {
   2961       constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
   2962 #if __has_builtin(__reference_constructs_from_temporary)
   2963       if constexpr (__n == 1)
   2964 	{
   2965 	  using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
   2966 	  static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
   2967 	}
   2968 #endif
   2969       return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
   2970 					 make_index_sequence<__n>{});
   2971     }
   2972 #endif
   2973 
   2974 #if __cpp_lib_tuple_like // >= C++23
   2975   template<__tuple_like _TTuple, __tuple_like _UTuple,
   2976 	   template<typename> class _TQual, template<typename> class _UQual,
   2977 	   typename = make_index_sequence<tuple_size_v<_TTuple>>>
   2978   struct __tuple_like_common_reference;
   2979 
   2980   template<__tuple_like _TTuple, __tuple_like _UTuple,
   2981 	   template<typename> class _TQual, template<typename> class _UQual,
   2982 	   size_t... _Is>
   2983     requires requires
   2984       { typename tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
   2985 					  _UQual<tuple_element_t<_Is, _UTuple>>>...>; }
   2986   struct __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual, index_sequence<_Is...>>
   2987   {
   2988     using type = tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
   2989 					  _UQual<tuple_element_t<_Is, _UTuple>>>...>;
   2990   };
   2991 
   2992   template<__tuple_like _TTuple, __tuple_like _UTuple,
   2993 	   template<typename> class _TQual, template<typename> class _UQual>
   2994     requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
   2995       && is_same_v<_TTuple, decay_t<_TTuple>>
   2996       && is_same_v<_UTuple, decay_t<_UTuple>>
   2997       && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
   2998       && requires { typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; }
   2999   struct basic_common_reference<_TTuple, _UTuple, _TQual, _UQual>
   3000   {
   3001     using type = typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type;
   3002   };
   3003 
   3004   template<__tuple_like _TTuple, __tuple_like _UTuple,
   3005 	   typename = make_index_sequence<tuple_size_v<_TTuple>>>
   3006   struct __tuple_like_common_type;
   3007 
   3008   template<__tuple_like _TTuple, __tuple_like _UTuple, size_t... _Is>
   3009     requires requires
   3010       { typename tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
   3011 				   tuple_element_t<_Is, _UTuple>>...>; }
   3012   struct __tuple_like_common_type<_TTuple, _UTuple, index_sequence<_Is...>>
   3013   {
   3014     using type = tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
   3015 				     tuple_element_t<_Is, _UTuple>>...>;
   3016   };
   3017 
   3018   template<__tuple_like _TTuple, __tuple_like _UTuple>
   3019     requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
   3020       && is_same_v<_TTuple, decay_t<_TTuple>>
   3021       && is_same_v<_UTuple, decay_t<_UTuple>>
   3022       && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
   3023       && requires { typename __tuple_like_common_type<_TTuple, _UTuple>::type; }
   3024   struct common_type<_TTuple, _UTuple>
   3025   {
   3026     using type = typename __tuple_like_common_type<_TTuple, _UTuple>::type;
   3027   };
   3028 #endif // C++23
   3029 
   3030   /// @}
   3031 
   3032 #undef __glibcxx_no_dangling_refs
   3033 
   3034 _GLIBCXX_END_NAMESPACE_VERSION
   3035 } // namespace std
   3036 
   3037 #endif // C++11
   3038 
   3039 #endif // _GLIBCXX_TUPLE
   3040