Home | History | Annotate | Line # | Download | only in std
tuple revision 1.1.1.16
      1 // <tuple> -*- C++ -*-
      2 
      3 // Copyright (C) 2007-2022 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::get, std::tuple_size etc.
     41 #include <bits/invoke.h>		// for std::__invoke
     42 #if __cplusplus > 201703L
     43 # include <compare>
     44 # define __cpp_lib_constexpr_tuple 201811L
     45 #endif
     46 
     47 namespace std _GLIBCXX_VISIBILITY(default)
     48 {
     49 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     50 
     51   /**
     52    *  @addtogroup utilities
     53    *  @{
     54    */
     55 
     56   template<typename... _Elements>
     57     class tuple;
     58 
     59   template<typename _Tp>
     60     struct __is_empty_non_tuple : is_empty<_Tp> { };
     61 
     62   // Using EBO for elements that are tuples causes ambiguous base errors.
     63   template<typename _El0, typename... _El>
     64     struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
     65 
     66   // Use the Empty Base-class Optimization for empty, non-final types.
     67   template<typename _Tp>
     68     using __empty_not_final
     69     = __conditional_t<__is_final(_Tp), false_type,
     70 		      __is_empty_non_tuple<_Tp>>;
     71 
     72   template<size_t _Idx, typename _Head,
     73 	   bool = __empty_not_final<_Head>::value>
     74     struct _Head_base;
     75 
     76 #if __has_cpp_attribute(__no_unique_address__)
     77   template<size_t _Idx, typename _Head>
     78     struct _Head_base<_Idx, _Head, true>
     79     {
     80       constexpr _Head_base()
     81       : _M_head_impl() { }
     82 
     83       constexpr _Head_base(const _Head& __h)
     84       : _M_head_impl(__h) { }
     85 
     86       constexpr _Head_base(const _Head_base&) = default;
     87       constexpr _Head_base(_Head_base&&) = default;
     88 
     89       template<typename _UHead>
     90 	constexpr _Head_base(_UHead&& __h)
     91 	: _M_head_impl(std::forward<_UHead>(__h)) { }
     92 
     93       _GLIBCXX20_CONSTEXPR
     94       _Head_base(allocator_arg_t, __uses_alloc0)
     95       : _M_head_impl() { }
     96 
     97       template<typename _Alloc>
     98 	_GLIBCXX20_CONSTEXPR
     99 	_Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
    100 	: _M_head_impl(allocator_arg, *__a._M_a) { }
    101 
    102       template<typename _Alloc>
    103 	_GLIBCXX20_CONSTEXPR
    104 	_Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
    105 	: _M_head_impl(*__a._M_a) { }
    106 
    107       template<typename _UHead>
    108 	_GLIBCXX20_CONSTEXPR
    109 	_Head_base(__uses_alloc0, _UHead&& __uhead)
    110 	: _M_head_impl(std::forward<_UHead>(__uhead)) { }
    111 
    112       template<typename _Alloc, typename _UHead>
    113 	_GLIBCXX20_CONSTEXPR
    114 	_Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
    115 	: _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
    116 	{ }
    117 
    118       template<typename _Alloc, typename _UHead>
    119 	_GLIBCXX20_CONSTEXPR
    120 	_Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
    121 	: _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
    122 
    123       static constexpr _Head&
    124       _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
    125 
    126       static constexpr const _Head&
    127       _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
    128 
    129       [[__no_unique_address__]] _Head _M_head_impl;
    130     };
    131 #else
    132   template<size_t _Idx, typename _Head>
    133     struct _Head_base<_Idx, _Head, true>
    134     : public _Head
    135     {
    136       constexpr _Head_base()
    137       : _Head() { }
    138 
    139       constexpr _Head_base(const _Head& __h)
    140       : _Head(__h) { }
    141 
    142       constexpr _Head_base(const _Head_base&) = default;
    143       constexpr _Head_base(_Head_base&&) = default;
    144 
    145       template<typename _UHead>
    146         constexpr _Head_base(_UHead&& __h)
    147 	: _Head(std::forward<_UHead>(__h)) { }
    148 
    149       _GLIBCXX20_CONSTEXPR
    150       _Head_base(allocator_arg_t, __uses_alloc0)
    151       : _Head() { }
    152 
    153       template<typename _Alloc>
    154 	_GLIBCXX20_CONSTEXPR
    155 	_Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
    156 	: _Head(allocator_arg, *__a._M_a) { }
    157 
    158       template<typename _Alloc>
    159 	_GLIBCXX20_CONSTEXPR
    160 	_Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
    161 	: _Head(*__a._M_a) { }
    162 
    163       template<typename _UHead>
    164 	_GLIBCXX20_CONSTEXPR
    165 	_Head_base(__uses_alloc0, _UHead&& __uhead)
    166 	: _Head(std::forward<_UHead>(__uhead)) { }
    167 
    168       template<typename _Alloc, typename _UHead>
    169 	_GLIBCXX20_CONSTEXPR
    170 	_Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
    171 	: _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
    172 
    173       template<typename _Alloc, typename _UHead>
    174 	_GLIBCXX20_CONSTEXPR
    175 	_Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
    176 	: _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
    177 
    178       static constexpr _Head&
    179       _M_head(_Head_base& __b) noexcept { return __b; }
    180 
    181       static constexpr const _Head&
    182       _M_head(const _Head_base& __b) noexcept { return __b; }
    183     };
    184 #endif
    185 
    186   template<size_t _Idx, typename _Head>
    187     struct _Head_base<_Idx, _Head, false>
    188     {
    189       constexpr _Head_base()
    190       : _M_head_impl() { }
    191 
    192       constexpr _Head_base(const _Head& __h)
    193       : _M_head_impl(__h) { }
    194 
    195       constexpr _Head_base(const _Head_base&) = default;
    196       constexpr _Head_base(_Head_base&&) = default;
    197 
    198       template<typename _UHead>
    199         constexpr _Head_base(_UHead&& __h)
    200 	: _M_head_impl(std::forward<_UHead>(__h)) { }
    201 
    202       _GLIBCXX20_CONSTEXPR
    203       _Head_base(allocator_arg_t, __uses_alloc0)
    204       : _M_head_impl() { }
    205 
    206       template<typename _Alloc>
    207 	_GLIBCXX20_CONSTEXPR
    208 	_Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
    209 	: _M_head_impl(allocator_arg, *__a._M_a) { }
    210 
    211       template<typename _Alloc>
    212 	_GLIBCXX20_CONSTEXPR
    213 	_Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
    214 	: _M_head_impl(*__a._M_a) { }
    215 
    216       template<typename _UHead>
    217 	_GLIBCXX20_CONSTEXPR
    218 	_Head_base(__uses_alloc0, _UHead&& __uhead)
    219 	: _M_head_impl(std::forward<_UHead>(__uhead)) { }
    220 
    221       template<typename _Alloc, typename _UHead>
    222 	_GLIBCXX20_CONSTEXPR
    223 	_Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
    224 	: _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
    225 	{ }
    226 
    227       template<typename _Alloc, typename _UHead>
    228 	_GLIBCXX20_CONSTEXPR
    229 	_Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
    230 	: _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
    231 
    232       static constexpr _Head&
    233       _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
    234 
    235       static constexpr const _Head&
    236       _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
    237 
    238       _Head _M_head_impl;
    239     };
    240 
    241   /**
    242    * Contains the actual implementation of the @c tuple template, stored
    243    * as a recursive inheritance hierarchy from the first element (most
    244    * derived class) to the last (least derived class). The @c Idx
    245    * parameter gives the 0-based index of the element stored at this
    246    * point in the hierarchy; we use it to implement a constant-time
    247    * get() operation.
    248    */
    249   template<size_t _Idx, typename... _Elements>
    250     struct _Tuple_impl;
    251 
    252   /**
    253    * Recursive tuple implementation. Here we store the @c Head element
    254    * and derive from a @c Tuple_impl containing the remaining elements
    255    * (which contains the @c Tail).
    256    */
    257   template<size_t _Idx, typename _Head, typename... _Tail>
    258     struct _Tuple_impl<_Idx, _Head, _Tail...>
    259     : public _Tuple_impl<_Idx + 1, _Tail...>,
    260       private _Head_base<_Idx, _Head>
    261     {
    262       template<size_t, typename...> friend struct _Tuple_impl;
    263 
    264       typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
    265       typedef _Head_base<_Idx, _Head> _Base;
    266 
    267       static constexpr _Head&
    268       _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
    269 
    270       static constexpr const _Head&
    271       _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
    272 
    273       static constexpr _Inherited&
    274       _M_tail(_Tuple_impl& __t) noexcept { return __t; }
    275 
    276       static constexpr const _Inherited&
    277       _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
    278 
    279       constexpr _Tuple_impl()
    280       : _Inherited(), _Base() { }
    281 
    282       explicit constexpr
    283       _Tuple_impl(const _Head& __head, const _Tail&... __tail)
    284       : _Inherited(__tail...), _Base(__head)
    285       { }
    286 
    287       template<typename _UHead, typename... _UTail,
    288 	       typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
    289 	explicit constexpr
    290 	_Tuple_impl(_UHead&& __head, _UTail&&... __tail)
    291 	: _Inherited(std::forward<_UTail>(__tail)...),
    292 	  _Base(std::forward<_UHead>(__head))
    293 	{ }
    294 
    295       constexpr _Tuple_impl(const _Tuple_impl&) = default;
    296 
    297       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    298       // 2729. Missing SFINAE on std::pair::operator=
    299       _Tuple_impl& operator=(const _Tuple_impl&) = delete;
    300 
    301       _Tuple_impl(_Tuple_impl&&) = default;
    302 
    303       template<typename... _UElements>
    304 	constexpr
    305 	_Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
    306 	: _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
    307 	  _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
    308 	{ }
    309 
    310       template<typename _UHead, typename... _UTails>
    311 	constexpr
    312 	_Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
    313 	: _Inherited(std::move
    314 		     (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
    315 	  _Base(std::forward<_UHead>
    316 		(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
    317 	{ }
    318 
    319       template<typename _Alloc>
    320 	_GLIBCXX20_CONSTEXPR
    321 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
    322 	: _Inherited(__tag, __a),
    323 	  _Base(__tag, __use_alloc<_Head>(__a))
    324 	{ }
    325 
    326       template<typename _Alloc>
    327 	_GLIBCXX20_CONSTEXPR
    328 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    329 		    const _Head& __head, const _Tail&... __tail)
    330 	: _Inherited(__tag, __a, __tail...),
    331 	  _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
    332 	{ }
    333 
    334       template<typename _Alloc, typename _UHead, typename... _UTail,
    335 	       typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
    336 	_GLIBCXX20_CONSTEXPR
    337 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    338 		    _UHead&& __head, _UTail&&... __tail)
    339 	: _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
    340 	  _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
    341 		std::forward<_UHead>(__head))
    342 	{ }
    343 
    344       template<typename _Alloc>
    345 	_GLIBCXX20_CONSTEXPR
    346 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    347 		    const _Tuple_impl& __in)
    348 	: _Inherited(__tag, __a, _M_tail(__in)),
    349 	  _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
    350 	{ }
    351 
    352       template<typename _Alloc>
    353 	_GLIBCXX20_CONSTEXPR
    354 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    355 		    _Tuple_impl&& __in)
    356 	: _Inherited(__tag, __a, std::move(_M_tail(__in))),
    357 	  _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
    358 		std::forward<_Head>(_M_head(__in)))
    359 	{ }
    360 
    361       template<typename _Alloc, typename _UHead, typename... _UTails>
    362 	_GLIBCXX20_CONSTEXPR
    363 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    364 		    const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
    365 	: _Inherited(__tag, __a,
    366 		     _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
    367 	  _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
    368 		_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
    369 	{ }
    370 
    371       template<typename _Alloc, typename _UHead, typename... _UTails>
    372 	_GLIBCXX20_CONSTEXPR
    373 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    374 		    _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
    375 	: _Inherited(__tag, __a, std::move
    376 		     (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
    377 	  _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
    378 		std::forward<_UHead>
    379 		(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
    380 	{ }
    381 
    382       template<typename... _UElements>
    383 	_GLIBCXX20_CONSTEXPR
    384 	void
    385 	_M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
    386 	{
    387 	  _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
    388 	  _M_tail(*this)._M_assign(
    389 	      _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
    390 	}
    391 
    392       template<typename _UHead, typename... _UTails>
    393 	_GLIBCXX20_CONSTEXPR
    394 	void
    395 	_M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
    396 	{
    397 	  _M_head(*this) = std::forward<_UHead>
    398 	    (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
    399 	  _M_tail(*this)._M_assign(
    400 	      std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
    401 	}
    402 
    403     protected:
    404       _GLIBCXX20_CONSTEXPR
    405       void
    406       _M_swap(_Tuple_impl& __in)
    407       {
    408 	using std::swap;
    409 	swap(_M_head(*this), _M_head(__in));
    410 	_Inherited::_M_swap(_M_tail(__in));
    411       }
    412     };
    413 
    414   // Basis case of inheritance recursion.
    415   template<size_t _Idx, typename _Head>
    416     struct _Tuple_impl<_Idx, _Head>
    417     : private _Head_base<_Idx, _Head>
    418     {
    419       template<size_t, typename...> friend struct _Tuple_impl;
    420 
    421       typedef _Head_base<_Idx, _Head> _Base;
    422 
    423       static constexpr _Head&
    424       _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
    425 
    426       static constexpr const _Head&
    427       _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
    428 
    429       constexpr
    430       _Tuple_impl()
    431       : _Base() { }
    432 
    433       explicit constexpr
    434       _Tuple_impl(const _Head& __head)
    435       : _Base(__head)
    436       { }
    437 
    438       template<typename _UHead>
    439 	explicit constexpr
    440 	_Tuple_impl(_UHead&& __head)
    441 	: _Base(std::forward<_UHead>(__head))
    442 	{ }
    443 
    444       constexpr _Tuple_impl(const _Tuple_impl&) = default;
    445 
    446       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    447       // 2729. Missing SFINAE on std::pair::operator=
    448       _Tuple_impl& operator=(const _Tuple_impl&) = delete;
    449 
    450 #if _GLIBCXX_INLINE_VERSION
    451       _Tuple_impl(_Tuple_impl&&) = default;
    452 #else
    453       constexpr
    454       _Tuple_impl(_Tuple_impl&& __in)
    455       noexcept(is_nothrow_move_constructible<_Head>::value)
    456       : _Base(static_cast<_Base&&>(__in))
    457       { }
    458 #endif
    459 
    460       template<typename _UHead>
    461 	constexpr
    462 	_Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
    463 	: _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
    464 	{ }
    465 
    466       template<typename _UHead>
    467 	constexpr
    468 	_Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
    469 	: _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
    470 	{ }
    471 
    472       template<typename _Alloc>
    473 	_GLIBCXX20_CONSTEXPR
    474 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
    475 	: _Base(__tag, __use_alloc<_Head>(__a))
    476 	{ }
    477 
    478       template<typename _Alloc>
    479 	_GLIBCXX20_CONSTEXPR
    480 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    481 		    const _Head& __head)
    482 	: _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
    483 	{ }
    484 
    485       template<typename _Alloc, typename _UHead>
    486 	_GLIBCXX20_CONSTEXPR
    487 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    488 		    _UHead&& __head)
    489 	: _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
    490 		std::forward<_UHead>(__head))
    491 	{ }
    492 
    493       template<typename _Alloc>
    494 	_GLIBCXX20_CONSTEXPR
    495 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    496 		    const _Tuple_impl& __in)
    497 	: _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
    498 	{ }
    499 
    500       template<typename _Alloc>
    501 	_GLIBCXX20_CONSTEXPR
    502 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    503 		    _Tuple_impl&& __in)
    504 	: _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
    505 		std::forward<_Head>(_M_head(__in)))
    506 	{ }
    507 
    508       template<typename _Alloc, typename _UHead>
    509 	_GLIBCXX20_CONSTEXPR
    510 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    511 		    const _Tuple_impl<_Idx, _UHead>& __in)
    512 	: _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
    513 		_Tuple_impl<_Idx, _UHead>::_M_head(__in))
    514 	{ }
    515 
    516       template<typename _Alloc, typename _UHead>
    517 	_GLIBCXX20_CONSTEXPR
    518 	_Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
    519 		    _Tuple_impl<_Idx, _UHead>&& __in)
    520 	: _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
    521 		std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
    522 	{ }
    523 
    524       template<typename _UHead>
    525 	_GLIBCXX20_CONSTEXPR
    526 	void
    527 	_M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
    528 	{
    529 	  _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
    530 	}
    531 
    532       template<typename _UHead>
    533 	_GLIBCXX20_CONSTEXPR
    534 	void
    535 	_M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
    536 	{
    537 	  _M_head(*this)
    538 	    = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
    539 	}
    540 
    541     protected:
    542       _GLIBCXX20_CONSTEXPR
    543       void
    544       _M_swap(_Tuple_impl& __in)
    545       {
    546 	using std::swap;
    547 	swap(_M_head(*this), _M_head(__in));
    548       }
    549     };
    550 
    551   // Concept utility functions, reused in conditionally-explicit
    552   // constructors.
    553   template<bool, typename... _Types>
    554     struct _TupleConstraints
    555     {
    556       // Constraint for a non-explicit constructor.
    557       // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
    558       // and every Ui is implicitly convertible to Ti.
    559       template<typename... _UTypes>
    560 	static constexpr bool __is_implicitly_constructible()
    561 	{
    562 	  return __and_<is_constructible<_Types, _UTypes>...,
    563 			is_convertible<_UTypes, _Types>...
    564 			>::value;
    565 	}
    566 
    567       // Constraint for a non-explicit constructor.
    568       // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
    569       // but not every Ui is implicitly convertible to Ti.
    570       template<typename... _UTypes>
    571 	static constexpr bool __is_explicitly_constructible()
    572 	{
    573 	  return __and_<is_constructible<_Types, _UTypes>...,
    574 			__not_<__and_<is_convertible<_UTypes, _Types>...>>
    575 			>::value;
    576 	}
    577 
    578       static constexpr bool __is_implicitly_default_constructible()
    579       {
    580 	return __and_<std::__is_implicitly_default_constructible<_Types>...
    581 		      >::value;
    582       }
    583 
    584       static constexpr bool __is_explicitly_default_constructible()
    585       {
    586 	return __and_<is_default_constructible<_Types>...,
    587 		      __not_<__and_<
    588 			std::__is_implicitly_default_constructible<_Types>...>
    589 		      >>::value;
    590       }
    591     };
    592 
    593   // Partial specialization used when a required precondition isn't met,
    594   // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
    595   template<typename... _Types>
    596     struct _TupleConstraints<false, _Types...>
    597     {
    598       template<typename... _UTypes>
    599 	static constexpr bool __is_implicitly_constructible()
    600 	{ return false; }
    601 
    602       template<typename... _UTypes>
    603 	static constexpr bool __is_explicitly_constructible()
    604 	{ return false; }
    605     };
    606 
    607   /// Primary class template, tuple
    608   template<typename... _Elements>
    609     class tuple : public _Tuple_impl<0, _Elements...>
    610     {
    611       typedef _Tuple_impl<0, _Elements...> _Inherited;
    612 
    613       template<bool _Cond>
    614 	using _TCC = _TupleConstraints<_Cond, _Elements...>;
    615 
    616       // Constraint for non-explicit default constructor
    617       template<bool _Dummy>
    618 	using _ImplicitDefaultCtor = __enable_if_t<
    619 	  _TCC<_Dummy>::__is_implicitly_default_constructible(),
    620 	  bool>;
    621 
    622       // Constraint for explicit default constructor
    623       template<bool _Dummy>
    624 	using _ExplicitDefaultCtor = __enable_if_t<
    625 	  _TCC<_Dummy>::__is_explicitly_default_constructible(),
    626 	  bool>;
    627 
    628       // Constraint for non-explicit constructors
    629       template<bool _Cond, typename... _Args>
    630 	using _ImplicitCtor = __enable_if_t<
    631 	  _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
    632 	  bool>;
    633 
    634       // Constraint for non-explicit constructors
    635       template<bool _Cond, typename... _Args>
    636 	using _ExplicitCtor = __enable_if_t<
    637 	  _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
    638 	  bool>;
    639 
    640       template<typename... _UElements>
    641 	static constexpr
    642 	__enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
    643 	__assignable()
    644 	{ return __and_<is_assignable<_Elements&, _UElements>...>::value; }
    645 
    646       // Condition for noexcept-specifier of an assignment operator.
    647       template<typename... _UElements>
    648 	static constexpr bool __nothrow_assignable()
    649 	{
    650 	  return
    651 	    __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
    652 	}
    653 
    654       // Condition for noexcept-specifier of a constructor.
    655       template<typename... _UElements>
    656 	static constexpr bool __nothrow_constructible()
    657 	{
    658 	  return
    659 	    __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
    660 	}
    661 
    662       // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
    663       template<typename _Up>
    664 	static constexpr bool __valid_args()
    665 	{
    666 	  return sizeof...(_Elements) == 1
    667 	    && !is_same<tuple, __remove_cvref_t<_Up>>::value;
    668 	}
    669 
    670       // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
    671       template<typename, typename, typename... _Tail>
    672 	static constexpr bool __valid_args()
    673 	{ return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
    674 
    675       /* Constraint for constructors with a tuple<UTypes...> parameter ensures
    676        * that the constructor is only viable when it would not interfere with
    677        * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
    678        * Such constructors are only viable if:
    679        * either sizeof...(Types) != 1,
    680        * or (when Types... expands to T and UTypes... expands to U)
    681        * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
    682        * and is_same_v<T, U> are all false.
    683        */
    684       template<typename _Tuple, typename = tuple,
    685 	       typename = __remove_cvref_t<_Tuple>>
    686 	struct _UseOtherCtor
    687 	: false_type
    688 	{ };
    689       // If TUPLE is convertible to the single element in *this,
    690       // then TUPLE should match tuple(UTypes&&...) instead.
    691       template<typename _Tuple, typename _Tp, typename _Up>
    692 	struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
    693 	: __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>
    694 	{ };
    695       // If TUPLE and *this each have a single element of the same type,
    696       // then TUPLE should match a copy/move constructor instead.
    697       template<typename _Tuple, typename _Tp>
    698 	struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
    699 	: true_type
    700 	{ };
    701 
    702       // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
    703       // and the single element in Types can be initialized from TUPLE,
    704       // or is the same type as tuple_element_t<0, TUPLE>.
    705       template<typename _Tuple>
    706 	static constexpr bool __use_other_ctor()
    707 	{ return _UseOtherCtor<_Tuple>::value; }
    708 
    709     public:
    710       template<typename _Dummy = void,
    711 	       _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
    712 	constexpr
    713 	tuple()
    714 	noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
    715 	: _Inherited() { }
    716 
    717       template<typename _Dummy = void,
    718 	       _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
    719 	explicit constexpr
    720 	tuple()
    721 	noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
    722 	: _Inherited() { }
    723 
    724       template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
    725 	       _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
    726 	constexpr
    727 	tuple(const _Elements&... __elements)
    728 	noexcept(__nothrow_constructible<const _Elements&...>())
    729 	: _Inherited(__elements...) { }
    730 
    731       template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
    732 	       _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
    733 	explicit constexpr
    734 	tuple(const _Elements&... __elements)
    735 	noexcept(__nothrow_constructible<const _Elements&...>())
    736 	: _Inherited(__elements...) { }
    737 
    738       template<typename... _UElements,
    739 	       bool _Valid = __valid_args<_UElements...>(),
    740 	       _ImplicitCtor<_Valid, _UElements...> = true>
    741 	constexpr
    742 	tuple(_UElements&&... __elements)
    743 	noexcept(__nothrow_constructible<_UElements...>())
    744 	: _Inherited(std::forward<_UElements>(__elements)...) { }
    745 
    746       template<typename... _UElements,
    747 	       bool _Valid = __valid_args<_UElements...>(),
    748 	       _ExplicitCtor<_Valid, _UElements...> = false>
    749 	explicit constexpr
    750 	tuple(_UElements&&... __elements)
    751 	noexcept(__nothrow_constructible<_UElements...>())
    752 	: _Inherited(std::forward<_UElements>(__elements)...) {	}
    753 
    754       constexpr tuple(const tuple&) = default;
    755 
    756       constexpr tuple(tuple&&) = default;
    757 
    758       template<typename... _UElements,
    759 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
    760 			   && !__use_other_ctor<const tuple<_UElements...>&>(),
    761 	       _ImplicitCtor<_Valid, const _UElements&...> = true>
    762 	constexpr
    763 	tuple(const tuple<_UElements...>& __in)
    764 	noexcept(__nothrow_constructible<const _UElements&...>())
    765 	: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
    766 	{ }
    767 
    768       template<typename... _UElements,
    769 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
    770 			   && !__use_other_ctor<const tuple<_UElements...>&>(),
    771 	       _ExplicitCtor<_Valid, const _UElements&...> = false>
    772 	explicit constexpr
    773 	tuple(const tuple<_UElements...>& __in)
    774 	noexcept(__nothrow_constructible<const _UElements&...>())
    775 	: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
    776 	{ }
    777 
    778       template<typename... _UElements,
    779 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
    780 			     && !__use_other_ctor<tuple<_UElements...>&&>(),
    781 	       _ImplicitCtor<_Valid, _UElements...> = true>
    782 	constexpr
    783 	tuple(tuple<_UElements...>&& __in)
    784 	noexcept(__nothrow_constructible<_UElements...>())
    785 	: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
    786 
    787       template<typename... _UElements,
    788 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
    789 			     && !__use_other_ctor<tuple<_UElements...>&&>(),
    790 	       _ExplicitCtor<_Valid, _UElements...> = false>
    791 	explicit constexpr
    792 	tuple(tuple<_UElements...>&& __in)
    793 	noexcept(__nothrow_constructible<_UElements...>())
    794 	: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
    795 
    796       // Allocator-extended constructors.
    797 
    798       template<typename _Alloc,
    799 	       _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
    800 	_GLIBCXX20_CONSTEXPR
    801 	tuple(allocator_arg_t __tag, const _Alloc& __a)
    802 	: _Inherited(__tag, __a) { }
    803 
    804       template<typename _Alloc,
    805 	       _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
    806 	_GLIBCXX20_CONSTEXPR
    807 	explicit
    808 	tuple(allocator_arg_t __tag, const _Alloc& __a)
    809 	: _Inherited(__tag, __a) { }
    810 
    811       template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
    812 	       _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
    813 	_GLIBCXX20_CONSTEXPR
    814 	tuple(allocator_arg_t __tag, const _Alloc& __a,
    815 	      const _Elements&... __elements)
    816 	: _Inherited(__tag, __a, __elements...) { }
    817 
    818       template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
    819 	       _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
    820 	_GLIBCXX20_CONSTEXPR
    821 	explicit
    822 	tuple(allocator_arg_t __tag, const _Alloc& __a,
    823 	      const _Elements&... __elements)
    824 	: _Inherited(__tag, __a, __elements...) { }
    825 
    826       template<typename _Alloc, typename... _UElements,
    827 	       bool _Valid = __valid_args<_UElements...>(),
    828 	       _ImplicitCtor<_Valid, _UElements...> = true>
    829 	_GLIBCXX20_CONSTEXPR
    830 	tuple(allocator_arg_t __tag, const _Alloc& __a,
    831 	      _UElements&&... __elements)
    832 	: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
    833 	{ }
    834 
    835       template<typename _Alloc, typename... _UElements,
    836 		 bool _Valid = __valid_args<_UElements...>(),
    837 	       _ExplicitCtor<_Valid, _UElements...> = false>
    838 	_GLIBCXX20_CONSTEXPR
    839 	explicit
    840 	tuple(allocator_arg_t __tag, const _Alloc& __a,
    841 	      _UElements&&... __elements)
    842 	: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
    843 	{ }
    844 
    845       template<typename _Alloc>
    846 	_GLIBCXX20_CONSTEXPR
    847 	tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
    848 	: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
    849 
    850       template<typename _Alloc>
    851 	_GLIBCXX20_CONSTEXPR
    852 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
    853 	: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
    854 
    855       template<typename _Alloc, typename... _UElements,
    856 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
    857 			     && !__use_other_ctor<const tuple<_UElements...>&>(),
    858 	       _ImplicitCtor<_Valid, const _UElements&...> = true>
    859 	_GLIBCXX20_CONSTEXPR
    860 	tuple(allocator_arg_t __tag, const _Alloc& __a,
    861 	      const tuple<_UElements...>& __in)
    862 	: _Inherited(__tag, __a,
    863 	             static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
    864 	{ }
    865 
    866       template<typename _Alloc, typename... _UElements,
    867 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
    868 			     && !__use_other_ctor<const tuple<_UElements...>&>(),
    869 	       _ExplicitCtor<_Valid, const _UElements&...> = false>
    870 	_GLIBCXX20_CONSTEXPR
    871 	explicit
    872 	tuple(allocator_arg_t __tag, const _Alloc& __a,
    873 	      const tuple<_UElements...>& __in)
    874 	: _Inherited(__tag, __a,
    875 	             static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
    876 	{ }
    877 
    878       template<typename _Alloc, typename... _UElements,
    879 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
    880 			     && !__use_other_ctor<tuple<_UElements...>&&>(),
    881 	       _ImplicitCtor<_Valid, _UElements...> = true>
    882 	_GLIBCXX20_CONSTEXPR
    883 	tuple(allocator_arg_t __tag, const _Alloc& __a,
    884 	      tuple<_UElements...>&& __in)
    885 	: _Inherited(__tag, __a,
    886 	             static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
    887 	{ }
    888 
    889       template<typename _Alloc, typename... _UElements,
    890 	       bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
    891 			     && !__use_other_ctor<tuple<_UElements...>&&>(),
    892 	       _ExplicitCtor<_Valid, _UElements...> = false>
    893 	_GLIBCXX20_CONSTEXPR
    894 	explicit
    895 	tuple(allocator_arg_t __tag, const _Alloc& __a,
    896 	      tuple<_UElements...>&& __in)
    897 	: _Inherited(__tag, __a,
    898 	             static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
    899 	{ }
    900 
    901       // tuple assignment
    902 
    903       _GLIBCXX20_CONSTEXPR
    904       tuple&
    905       operator=(__conditional_t<__assignable<const _Elements&...>(),
    906 				const tuple&,
    907 				const __nonesuch&> __in)
    908       noexcept(__nothrow_assignable<const _Elements&...>())
    909       {
    910 	this->_M_assign(__in);
    911 	return *this;
    912       }
    913 
    914       _GLIBCXX20_CONSTEXPR
    915       tuple&
    916       operator=(__conditional_t<__assignable<_Elements...>(),
    917 				tuple&&,
    918 				__nonesuch&&> __in)
    919       noexcept(__nothrow_assignable<_Elements...>())
    920       {
    921 	this->_M_assign(std::move(__in));
    922 	return *this;
    923       }
    924 
    925       template<typename... _UElements>
    926 	_GLIBCXX20_CONSTEXPR
    927 	__enable_if_t<__assignable<const _UElements&...>(), tuple&>
    928 	operator=(const tuple<_UElements...>& __in)
    929 	noexcept(__nothrow_assignable<const _UElements&...>())
    930 	{
    931 	  this->_M_assign(__in);
    932 	  return *this;
    933 	}
    934 
    935       template<typename... _UElements>
    936 	_GLIBCXX20_CONSTEXPR
    937 	__enable_if_t<__assignable<_UElements...>(), tuple&>
    938 	operator=(tuple<_UElements...>&& __in)
    939 	noexcept(__nothrow_assignable<_UElements...>())
    940 	{
    941 	  this->_M_assign(std::move(__in));
    942 	  return *this;
    943 	}
    944 
    945       // tuple swap
    946       _GLIBCXX20_CONSTEXPR
    947       void
    948       swap(tuple& __in)
    949       noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
    950       { _Inherited::_M_swap(__in); }
    951     };
    952 
    953 #if __cpp_deduction_guides >= 201606
    954   template<typename... _UTypes>
    955     tuple(_UTypes...) -> tuple<_UTypes...>;
    956   template<typename _T1, typename _T2>
    957     tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
    958   template<typename _Alloc, typename... _UTypes>
    959     tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
    960   template<typename _Alloc, typename _T1, typename _T2>
    961     tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
    962   template<typename _Alloc, typename... _UTypes>
    963     tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
    964 #endif
    965 
    966   // Explicit specialization, zero-element tuple.
    967   template<>
    968     class tuple<>
    969     {
    970     public:
    971       _GLIBCXX20_CONSTEXPR
    972       void swap(tuple&) noexcept { /* no-op */ }
    973       // We need the default since we're going to define no-op
    974       // allocator constructors.
    975       tuple() = default;
    976       // No-op allocator constructors.
    977       template<typename _Alloc>
    978 	_GLIBCXX20_CONSTEXPR
    979 	tuple(allocator_arg_t, const _Alloc&) noexcept { }
    980       template<typename _Alloc>
    981 	_GLIBCXX20_CONSTEXPR
    982 	tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
    983     };
    984 
    985   /// Partial specialization, 2-element tuple.
    986   /// Includes construction and assignment from a pair.
    987   template<typename _T1, typename _T2>
    988     class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
    989     {
    990       typedef _Tuple_impl<0, _T1, _T2> _Inherited;
    991 
    992       // Constraint for non-explicit default constructor
    993       template<bool _Dummy, typename _U1, typename _U2>
    994 	using _ImplicitDefaultCtor = __enable_if_t<
    995 	  _TupleConstraints<_Dummy, _U1, _U2>::
    996 	    __is_implicitly_default_constructible(),
    997 	  bool>;
    998 
    999       // Constraint for explicit default constructor
   1000       template<bool _Dummy, typename _U1, typename _U2>
   1001 	using _ExplicitDefaultCtor = __enable_if_t<
   1002 	  _TupleConstraints<_Dummy, _U1, _U2>::
   1003 	    __is_explicitly_default_constructible(),
   1004 	  bool>;
   1005 
   1006       template<bool _Dummy>
   1007 	using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
   1008 
   1009       // Constraint for non-explicit constructors
   1010       template<bool _Cond, typename _U1, typename _U2>
   1011 	using _ImplicitCtor = __enable_if_t<
   1012 	  _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
   1013 	  bool>;
   1014 
   1015       // Constraint for non-explicit constructors
   1016       template<bool _Cond, typename _U1, typename _U2>
   1017 	using _ExplicitCtor = __enable_if_t<
   1018 	  _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
   1019 	  bool>;
   1020 
   1021       template<typename _U1, typename _U2>
   1022 	static constexpr bool __assignable()
   1023 	{
   1024 	  return __and_<is_assignable<_T1&, _U1>,
   1025 			is_assignable<_T2&, _U2>>::value;
   1026 	}
   1027 
   1028       template<typename _U1, typename _U2>
   1029 	static constexpr bool __nothrow_assignable()
   1030 	{
   1031 	  return __and_<is_nothrow_assignable<_T1&, _U1>,
   1032 			is_nothrow_assignable<_T2&, _U2>>::value;
   1033 	}
   1034 
   1035       template<typename _U1, typename _U2>
   1036 	static constexpr bool __nothrow_constructible()
   1037 	{
   1038 	  return __and_<is_nothrow_constructible<_T1, _U1>,
   1039 			    is_nothrow_constructible<_T2, _U2>>::value;
   1040 	}
   1041 
   1042       static constexpr bool __nothrow_default_constructible()
   1043       {
   1044 	return __and_<is_nothrow_default_constructible<_T1>,
   1045 		      is_nothrow_default_constructible<_T2>>::value;
   1046       }
   1047 
   1048       template<typename _U1>
   1049 	static constexpr bool __is_alloc_arg()
   1050 	{ return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
   1051 
   1052     public:
   1053       template<bool _Dummy = true,
   1054 	       _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
   1055 	constexpr
   1056 	tuple()
   1057 	noexcept(__nothrow_default_constructible())
   1058 	: _Inherited() { }
   1059 
   1060       template<bool _Dummy = true,
   1061 	       _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
   1062 	explicit constexpr
   1063 	tuple()
   1064 	noexcept(__nothrow_default_constructible())
   1065 	: _Inherited() { }
   1066 
   1067       template<bool _Dummy = true,
   1068 	       _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
   1069 	constexpr
   1070 	tuple(const _T1& __a1, const _T2& __a2)
   1071 	noexcept(__nothrow_constructible<const _T1&, const _T2&>())
   1072 	: _Inherited(__a1, __a2) { }
   1073 
   1074       template<bool _Dummy = true,
   1075 	       _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
   1076 	explicit constexpr
   1077 	tuple(const _T1& __a1, const _T2& __a2)
   1078 	noexcept(__nothrow_constructible<const _T1&, const _T2&>())
   1079 	: _Inherited(__a1, __a2) { }
   1080 
   1081       template<typename _U1, typename _U2,
   1082 	       _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
   1083 	constexpr
   1084 	tuple(_U1&& __a1, _U2&& __a2)
   1085 	noexcept(__nothrow_constructible<_U1, _U2>())
   1086 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
   1087 
   1088       template<typename _U1, typename _U2,
   1089 	       _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
   1090 	explicit constexpr
   1091 	tuple(_U1&& __a1, _U2&& __a2)
   1092 	noexcept(__nothrow_constructible<_U1, _U2>())
   1093 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
   1094 
   1095       constexpr tuple(const tuple&) = default;
   1096 
   1097       constexpr tuple(tuple&&) = default;
   1098 
   1099       template<typename _U1, typename _U2,
   1100 	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
   1101 	constexpr
   1102 	tuple(const tuple<_U1, _U2>& __in)
   1103 	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
   1104 	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
   1105 
   1106       template<typename _U1, typename _U2,
   1107 	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
   1108 	explicit constexpr
   1109 	tuple(const tuple<_U1, _U2>& __in)
   1110 	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
   1111 	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
   1112 
   1113       template<typename _U1, typename _U2,
   1114 	       _ImplicitCtor<true, _U1, _U2> = true>
   1115 	constexpr
   1116 	tuple(tuple<_U1, _U2>&& __in)
   1117 	noexcept(__nothrow_constructible<_U1, _U2>())
   1118 	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
   1119 
   1120       template<typename _U1, typename _U2,
   1121 	       _ExplicitCtor<true, _U1, _U2> = false>
   1122 	explicit constexpr
   1123 	tuple(tuple<_U1, _U2>&& __in)
   1124 	noexcept(__nothrow_constructible<_U1, _U2>())
   1125 	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
   1126 
   1127       template<typename _U1, typename _U2,
   1128 	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
   1129 	constexpr
   1130 	tuple(const pair<_U1, _U2>& __in)
   1131 	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
   1132 	: _Inherited(__in.first, __in.second) { }
   1133 
   1134       template<typename _U1, typename _U2,
   1135 	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
   1136 	explicit constexpr
   1137 	tuple(const pair<_U1, _U2>& __in)
   1138 	noexcept(__nothrow_constructible<const _U1&, const _U2&>())
   1139 	: _Inherited(__in.first, __in.second) { }
   1140 
   1141       template<typename _U1, typename _U2,
   1142 	       _ImplicitCtor<true, _U1, _U2> = true>
   1143 	constexpr
   1144 	tuple(pair<_U1, _U2>&& __in)
   1145 	noexcept(__nothrow_constructible<_U1, _U2>())
   1146 	: _Inherited(std::forward<_U1>(__in.first),
   1147 		     std::forward<_U2>(__in.second)) { }
   1148 
   1149       template<typename _U1, typename _U2,
   1150 	       _ExplicitCtor<true, _U1, _U2> = false>
   1151 	explicit constexpr
   1152 	tuple(pair<_U1, _U2>&& __in)
   1153 	noexcept(__nothrow_constructible<_U1, _U2>())
   1154 	: _Inherited(std::forward<_U1>(__in.first),
   1155 		     std::forward<_U2>(__in.second)) { }
   1156 
   1157       // Allocator-extended constructors.
   1158 
   1159       template<typename _Alloc,
   1160 	       _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
   1161 	_GLIBCXX20_CONSTEXPR
   1162 	tuple(allocator_arg_t __tag, const _Alloc& __a)
   1163 	: _Inherited(__tag, __a) { }
   1164 
   1165       template<typename _Alloc,
   1166 	       _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
   1167 	_GLIBCXX20_CONSTEXPR
   1168 	explicit
   1169 	tuple(allocator_arg_t __tag, const _Alloc& __a)
   1170 	: _Inherited(__tag, __a) { }
   1171 
   1172       template<typename _Alloc, bool _Dummy = true,
   1173 	       _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
   1174 	_GLIBCXX20_CONSTEXPR
   1175 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1176 	      const _T1& __a1, const _T2& __a2)
   1177 	: _Inherited(__tag, __a, __a1, __a2) { }
   1178 
   1179       template<typename _Alloc, bool _Dummy = true,
   1180 	       _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
   1181 	explicit
   1182 	_GLIBCXX20_CONSTEXPR
   1183 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1184 	      const _T1& __a1, const _T2& __a2)
   1185 	: _Inherited(__tag, __a, __a1, __a2) { }
   1186 
   1187       template<typename _Alloc, typename _U1, typename _U2,
   1188 	       _ImplicitCtor<true, _U1, _U2> = true>
   1189 	_GLIBCXX20_CONSTEXPR
   1190 	tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
   1191 	: _Inherited(__tag, __a, std::forward<_U1>(__a1),
   1192 	             std::forward<_U2>(__a2)) { }
   1193 
   1194       template<typename _Alloc, typename _U1, typename _U2,
   1195 	       _ExplicitCtor<true, _U1, _U2> = false>
   1196 	explicit
   1197 	_GLIBCXX20_CONSTEXPR
   1198 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1199 	      _U1&& __a1, _U2&& __a2)
   1200 	: _Inherited(__tag, __a, std::forward<_U1>(__a1),
   1201 	             std::forward<_U2>(__a2)) { }
   1202 
   1203       template<typename _Alloc>
   1204 	_GLIBCXX20_CONSTEXPR
   1205 	tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
   1206 	: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
   1207 
   1208       template<typename _Alloc>
   1209 	_GLIBCXX20_CONSTEXPR
   1210 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
   1211 	: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
   1212 
   1213       template<typename _Alloc, typename _U1, typename _U2,
   1214 	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
   1215 	_GLIBCXX20_CONSTEXPR
   1216 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1217 	      const tuple<_U1, _U2>& __in)
   1218 	: _Inherited(__tag, __a,
   1219 	             static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
   1220 	{ }
   1221 
   1222       template<typename _Alloc, typename _U1, typename _U2,
   1223 	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
   1224 	explicit
   1225 	_GLIBCXX20_CONSTEXPR
   1226 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1227 	      const tuple<_U1, _U2>& __in)
   1228 	: _Inherited(__tag, __a,
   1229 	             static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
   1230 	{ }
   1231 
   1232       template<typename _Alloc, typename _U1, typename _U2,
   1233 	       _ImplicitCtor<true, _U1, _U2> = true>
   1234 	_GLIBCXX20_CONSTEXPR
   1235 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
   1236 	: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
   1237 	{ }
   1238 
   1239       template<typename _Alloc, typename _U1, typename _U2,
   1240 	       _ExplicitCtor<true, _U1, _U2> = false>
   1241 	explicit
   1242 	_GLIBCXX20_CONSTEXPR
   1243 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
   1244 	: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
   1245 	{ }
   1246 
   1247       template<typename _Alloc, typename _U1, typename _U2,
   1248 	       _ImplicitCtor<true, const _U1&, const _U2&> = true>
   1249 	_GLIBCXX20_CONSTEXPR
   1250 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1251 	      const pair<_U1, _U2>& __in)
   1252 	: _Inherited(__tag, __a, __in.first, __in.second) { }
   1253 
   1254       template<typename _Alloc, typename _U1, typename _U2,
   1255 	       _ExplicitCtor<true, const _U1&, const _U2&> = false>
   1256 	explicit
   1257 	_GLIBCXX20_CONSTEXPR
   1258 	tuple(allocator_arg_t __tag, const _Alloc& __a,
   1259 	      const pair<_U1, _U2>& __in)
   1260 	: _Inherited(__tag, __a, __in.first, __in.second) { }
   1261 
   1262       template<typename _Alloc, typename _U1, typename _U2,
   1263 	       _ImplicitCtor<true, _U1, _U2> = true>
   1264 	_GLIBCXX20_CONSTEXPR
   1265 	tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
   1266 	: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
   1267 		     std::forward<_U2>(__in.second)) { }
   1268 
   1269       template<typename _Alloc, typename _U1, typename _U2,
   1270 	       _ExplicitCtor<true, _U1, _U2> = false>
   1271 	explicit
   1272 	_GLIBCXX20_CONSTEXPR
   1273 	tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
   1274 	: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
   1275 		     std::forward<_U2>(__in.second)) { }
   1276 
   1277       // Tuple assignment.
   1278 
   1279       _GLIBCXX20_CONSTEXPR
   1280       tuple&
   1281       operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
   1282 				const tuple&,
   1283 				const __nonesuch&> __in)
   1284       noexcept(__nothrow_assignable<const _T1&, const _T2&>())
   1285       {
   1286 	this->_M_assign(__in);
   1287 	return *this;
   1288       }
   1289 
   1290       _GLIBCXX20_CONSTEXPR
   1291       tuple&
   1292       operator=(__conditional_t<__assignable<_T1, _T2>(),
   1293 				tuple&&,
   1294 				__nonesuch&&> __in)
   1295       noexcept(__nothrow_assignable<_T1, _T2>())
   1296       {
   1297 	this->_M_assign(std::move(__in));
   1298 	return *this;
   1299       }
   1300 
   1301       template<typename _U1, typename _U2>
   1302 	_GLIBCXX20_CONSTEXPR
   1303 	__enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
   1304 	operator=(const tuple<_U1, _U2>& __in)
   1305 	noexcept(__nothrow_assignable<const _U1&, const _U2&>())
   1306 	{
   1307 	  this->_M_assign(__in);
   1308 	  return *this;
   1309 	}
   1310 
   1311       template<typename _U1, typename _U2>
   1312 	_GLIBCXX20_CONSTEXPR
   1313 	__enable_if_t<__assignable<_U1, _U2>(), tuple&>
   1314 	operator=(tuple<_U1, _U2>&& __in)
   1315 	noexcept(__nothrow_assignable<_U1, _U2>())
   1316 	{
   1317 	  this->_M_assign(std::move(__in));
   1318 	  return *this;
   1319 	}
   1320 
   1321       template<typename _U1, typename _U2>
   1322 	_GLIBCXX20_CONSTEXPR
   1323 	__enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
   1324 	operator=(const pair<_U1, _U2>& __in)
   1325 	noexcept(__nothrow_assignable<const _U1&, const _U2&>())
   1326 	{
   1327 	  this->_M_head(*this) = __in.first;
   1328 	  this->_M_tail(*this)._M_head(*this) = __in.second;
   1329 	  return *this;
   1330 	}
   1331 
   1332       template<typename _U1, typename _U2>
   1333 	_GLIBCXX20_CONSTEXPR
   1334 	__enable_if_t<__assignable<_U1, _U2>(), tuple&>
   1335 	operator=(pair<_U1, _U2>&& __in)
   1336 	noexcept(__nothrow_assignable<_U1, _U2>())
   1337 	{
   1338 	  this->_M_head(*this) = std::forward<_U1>(__in.first);
   1339 	  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
   1340 	  return *this;
   1341 	}
   1342 
   1343       _GLIBCXX20_CONSTEXPR
   1344       void
   1345       swap(tuple& __in)
   1346       noexcept(__and_<__is_nothrow_swappable<_T1>,
   1347 		      __is_nothrow_swappable<_T2>>::value)
   1348       { _Inherited::_M_swap(__in); }
   1349     };
   1350 
   1351 
   1352   /// class tuple_size
   1353   template<typename... _Elements>
   1354     struct tuple_size<tuple<_Elements...>>
   1355     : public integral_constant<size_t, sizeof...(_Elements)> { };
   1356 
   1357 #if __cplusplus >= 201703L
   1358   template<typename... _Types>
   1359     inline constexpr size_t tuple_size_v<tuple<_Types...>>
   1360       = sizeof...(_Types);
   1361 
   1362   template<typename... _Types>
   1363     inline constexpr size_t tuple_size_v<const tuple<_Types...>>
   1364       = sizeof...(_Types);
   1365 #endif
   1366 
   1367   /// Trait to get the Ith element type from a tuple.
   1368   template<size_t __i, typename... _Types>
   1369     struct tuple_element<__i, tuple<_Types...>>
   1370     {
   1371       static_assert(__i < sizeof...(_Types), "tuple index must be in range");
   1372 
   1373       using type = typename _Nth_type<__i, _Types...>::type;
   1374     };
   1375 
   1376   template<size_t __i, typename _Head, typename... _Tail>
   1377     constexpr _Head&
   1378     __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
   1379     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
   1380 
   1381   template<size_t __i, typename _Head, typename... _Tail>
   1382     constexpr const _Head&
   1383     __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
   1384     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
   1385 
   1386   // Deleted overload to improve diagnostics for invalid indices
   1387   template<size_t __i, typename... _Types>
   1388     __enable_if_t<(__i >= sizeof...(_Types))>
   1389     __get_helper(const tuple<_Types...>&) = delete;
   1390 
   1391   /// Return a reference to the ith element of a tuple.
   1392   template<size_t __i, typename... _Elements>
   1393     constexpr __tuple_element_t<__i, tuple<_Elements...>>&
   1394     get(tuple<_Elements...>& __t) noexcept
   1395     { return std::__get_helper<__i>(__t); }
   1396 
   1397   /// Return a const reference to the ith element of a const tuple.
   1398   template<size_t __i, typename... _Elements>
   1399     constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
   1400     get(const tuple<_Elements...>& __t) noexcept
   1401     { return std::__get_helper<__i>(__t); }
   1402 
   1403   /// Return an rvalue reference to the ith element of a tuple rvalue.
   1404   template<size_t __i, typename... _Elements>
   1405     constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
   1406     get(tuple<_Elements...>&& __t) noexcept
   1407     {
   1408       typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
   1409       return std::forward<__element_type>(std::__get_helper<__i>(__t));
   1410     }
   1411 
   1412   /// Return a const rvalue reference to the ith element of a const tuple rvalue.
   1413   template<size_t __i, typename... _Elements>
   1414     constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
   1415     get(const tuple<_Elements...>&& __t) noexcept
   1416     {
   1417       typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
   1418       return std::forward<const __element_type>(std::__get_helper<__i>(__t));
   1419     }
   1420 
   1421   /// @cond undocumented
   1422   // Deleted overload chosen for invalid indices.
   1423   template<size_t __i, typename... _Elements>
   1424     constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
   1425     get(const tuple<_Elements...>&) = delete;
   1426   /// @endcond
   1427 
   1428 #if __cplusplus >= 201402L
   1429 
   1430 #define __cpp_lib_tuples_by_type 201304L
   1431 
   1432   /// Return a reference to the unique element of type _Tp of a tuple.
   1433   template <typename _Tp, typename... _Types>
   1434     constexpr _Tp&
   1435     get(tuple<_Types...>& __t) noexcept
   1436     {
   1437       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
   1438       static_assert(__idx < sizeof...(_Types),
   1439 	  "the type T in std::get<T> must occur exactly once in the tuple");
   1440       return std::__get_helper<__idx>(__t);
   1441     }
   1442 
   1443   /// Return a reference to the unique element of type _Tp of a tuple rvalue.
   1444   template <typename _Tp, typename... _Types>
   1445     constexpr _Tp&&
   1446     get(tuple<_Types...>&& __t) noexcept
   1447     {
   1448       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
   1449       static_assert(__idx < sizeof...(_Types),
   1450 	  "the type T in std::get<T> must occur exactly once in the tuple");
   1451       return std::forward<_Tp>(std::__get_helper<__idx>(__t));
   1452     }
   1453 
   1454   /// Return a const reference to the unique element of type _Tp of a tuple.
   1455   template <typename _Tp, typename... _Types>
   1456     constexpr const _Tp&
   1457     get(const tuple<_Types...>& __t) noexcept
   1458     {
   1459       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
   1460       static_assert(__idx < sizeof...(_Types),
   1461 	  "the type T in std::get<T> must occur exactly once in the tuple");
   1462       return std::__get_helper<__idx>(__t);
   1463     }
   1464 
   1465   /// Return a const reference to the unique element of type _Tp of
   1466   /// a const tuple rvalue.
   1467   template <typename _Tp, typename... _Types>
   1468     constexpr const _Tp&&
   1469     get(const tuple<_Types...>&& __t) noexcept
   1470     {
   1471       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
   1472       static_assert(__idx < sizeof...(_Types),
   1473 	  "the type T in std::get<T> must occur exactly once in the tuple");
   1474       return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
   1475     }
   1476 #endif
   1477 
   1478   // This class performs the comparison operations on tuples
   1479   template<typename _Tp, typename _Up, size_t __i, size_t __size>
   1480     struct __tuple_compare
   1481     {
   1482       static constexpr bool
   1483       __eq(const _Tp& __t, const _Up& __u)
   1484       {
   1485 	return bool(std::get<__i>(__t) == std::get<__i>(__u))
   1486 	  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
   1487       }
   1488 
   1489       static constexpr bool
   1490       __less(const _Tp& __t, const _Up& __u)
   1491       {
   1492 	return bool(std::get<__i>(__t) < std::get<__i>(__u))
   1493 	  || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
   1494 	      && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
   1495       }
   1496     };
   1497 
   1498   template<typename _Tp, typename _Up, size_t __size>
   1499     struct __tuple_compare<_Tp, _Up, __size, __size>
   1500     {
   1501       static constexpr bool
   1502       __eq(const _Tp&, const _Up&) { return true; }
   1503 
   1504       static constexpr bool
   1505       __less(const _Tp&, const _Up&) { return false; }
   1506     };
   1507 
   1508   template<typename... _TElements, typename... _UElements>
   1509     constexpr bool
   1510     operator==(const tuple<_TElements...>& __t,
   1511 	       const tuple<_UElements...>& __u)
   1512     {
   1513       static_assert(sizeof...(_TElements) == sizeof...(_UElements),
   1514 	  "tuple objects can only be compared if they have equal sizes.");
   1515       using __compare = __tuple_compare<tuple<_TElements...>,
   1516 					tuple<_UElements...>,
   1517 					0, sizeof...(_TElements)>;
   1518       return __compare::__eq(__t, __u);
   1519     }
   1520 
   1521 #if __cpp_lib_three_way_comparison
   1522   template<typename _Cat, typename _Tp, typename _Up>
   1523     constexpr _Cat
   1524     __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
   1525     { return _Cat::equivalent; }
   1526 
   1527   template<typename _Cat, typename _Tp, typename _Up,
   1528 	   size_t _Idx0, size_t... _Idxs>
   1529     constexpr _Cat
   1530     __tuple_cmp(const _Tp& __t, const _Up& __u,
   1531 		index_sequence<_Idx0, _Idxs...>)
   1532     {
   1533       auto __c
   1534 	= __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
   1535       if (__c != 0)
   1536 	return __c;
   1537       return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
   1538     }
   1539 
   1540   template<typename... _Tps, typename... _Ups>
   1541     constexpr
   1542     common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
   1543     operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
   1544     {
   1545       using _Cat
   1546 	= common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
   1547       return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
   1548     }
   1549 #else
   1550   template<typename... _TElements, typename... _UElements>
   1551     constexpr bool
   1552     operator<(const tuple<_TElements...>& __t,
   1553 	      const tuple<_UElements...>& __u)
   1554     {
   1555       static_assert(sizeof...(_TElements) == sizeof...(_UElements),
   1556 	  "tuple objects can only be compared if they have equal sizes.");
   1557       using __compare = __tuple_compare<tuple<_TElements...>,
   1558 					tuple<_UElements...>,
   1559 					0, sizeof...(_TElements)>;
   1560       return __compare::__less(__t, __u);
   1561     }
   1562 
   1563   template<typename... _TElements, typename... _UElements>
   1564     constexpr bool
   1565     operator!=(const tuple<_TElements...>& __t,
   1566 	       const tuple<_UElements...>& __u)
   1567     { return !(__t == __u); }
   1568 
   1569   template<typename... _TElements, typename... _UElements>
   1570     constexpr bool
   1571     operator>(const tuple<_TElements...>& __t,
   1572 	      const tuple<_UElements...>& __u)
   1573     { return __u < __t; }
   1574 
   1575   template<typename... _TElements, typename... _UElements>
   1576     constexpr bool
   1577     operator<=(const tuple<_TElements...>& __t,
   1578 	       const tuple<_UElements...>& __u)
   1579     { return !(__u < __t); }
   1580 
   1581   template<typename... _TElements, typename... _UElements>
   1582     constexpr bool
   1583     operator>=(const tuple<_TElements...>& __t,
   1584 	       const tuple<_UElements...>& __u)
   1585     { return !(__t < __u); }
   1586 #endif // three_way_comparison
   1587 
   1588   // NB: DR 705.
   1589   /// Create a tuple containing copies of the arguments
   1590   template<typename... _Elements>
   1591     constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
   1592     make_tuple(_Elements&&... __args)
   1593     {
   1594       typedef tuple<typename __decay_and_strip<_Elements>::__type...>
   1595 	__result_type;
   1596       return __result_type(std::forward<_Elements>(__args)...);
   1597     }
   1598 
   1599   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   1600   // 2275. Why is forward_as_tuple not constexpr?
   1601   /// Create a tuple of lvalue or rvalue references to the arguments
   1602   template<typename... _Elements>
   1603     constexpr tuple<_Elements&&...>
   1604     forward_as_tuple(_Elements&&... __args) noexcept
   1605     { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
   1606 
   1607   // Declarations of std::array and its std::get overloads, so that
   1608   // std::tuple_cat can use them if <tuple> is included before <array>.
   1609 
   1610   template<typename _Tp, size_t _Nm> struct array;
   1611 
   1612   template<size_t _Int, typename _Tp, size_t _Nm>
   1613     constexpr _Tp&
   1614     get(array<_Tp, _Nm>&) noexcept;
   1615 
   1616   template<size_t _Int, typename _Tp, size_t _Nm>
   1617     constexpr _Tp&&
   1618     get(array<_Tp, _Nm>&&) noexcept;
   1619 
   1620   template<size_t _Int, typename _Tp, size_t _Nm>
   1621     constexpr const _Tp&
   1622     get(const array<_Tp, _Nm>&) noexcept;
   1623 
   1624   template<size_t _Int, typename _Tp, size_t _Nm>
   1625     constexpr const _Tp&&
   1626     get(const array<_Tp, _Nm>&&) noexcept;
   1627 
   1628   /// @cond undocumented
   1629   template<size_t, typename, typename, size_t>
   1630     struct __make_tuple_impl;
   1631 
   1632   template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
   1633     struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
   1634     : __make_tuple_impl<_Idx + 1,
   1635 			tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
   1636 			_Tuple, _Nm>
   1637     { };
   1638 
   1639   template<size_t _Nm, typename _Tuple, typename... _Tp>
   1640     struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
   1641     {
   1642       typedef tuple<_Tp...> __type;
   1643     };
   1644 
   1645   template<typename _Tuple>
   1646     struct __do_make_tuple
   1647     : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
   1648     { };
   1649 
   1650   // Returns the std::tuple equivalent of a tuple-like type.
   1651   template<typename _Tuple>
   1652     struct __make_tuple
   1653     : public __do_make_tuple<__remove_cvref_t<_Tuple>>
   1654     { };
   1655 
   1656   // Combines several std::tuple's into a single one.
   1657   template<typename...>
   1658     struct __combine_tuples;
   1659 
   1660   template<>
   1661     struct __combine_tuples<>
   1662     {
   1663       typedef tuple<> __type;
   1664     };
   1665 
   1666   template<typename... _Ts>
   1667     struct __combine_tuples<tuple<_Ts...>>
   1668     {
   1669       typedef tuple<_Ts...> __type;
   1670     };
   1671 
   1672   template<typename... _T1s, typename... _T2s, typename... _Rem>
   1673     struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
   1674     {
   1675       typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
   1676 					_Rem...>::__type __type;
   1677     };
   1678 
   1679   // Computes the result type of tuple_cat given a set of tuple-like types.
   1680   template<typename... _Tpls>
   1681     struct __tuple_cat_result
   1682     {
   1683       typedef typename __combine_tuples
   1684         <typename __make_tuple<_Tpls>::__type...>::__type __type;
   1685     };
   1686 
   1687   // Helper to determine the index set for the first tuple-like
   1688   // type of a given set.
   1689   template<typename...>
   1690     struct __make_1st_indices;
   1691 
   1692   template<>
   1693     struct __make_1st_indices<>
   1694     {
   1695       typedef _Index_tuple<> __type;
   1696     };
   1697 
   1698   template<typename _Tp, typename... _Tpls>
   1699     struct __make_1st_indices<_Tp, _Tpls...>
   1700     {
   1701       typedef typename _Build_index_tuple<tuple_size<
   1702 	typename remove_reference<_Tp>::type>::value>::__type __type;
   1703     };
   1704 
   1705   // Performs the actual concatenation by step-wise expanding tuple-like
   1706   // objects into the elements,  which are finally forwarded into the
   1707   // result tuple.
   1708   template<typename _Ret, typename _Indices, typename... _Tpls>
   1709     struct __tuple_concater;
   1710 
   1711   template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
   1712     struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
   1713     {
   1714       template<typename... _Us>
   1715         static constexpr _Ret
   1716         _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
   1717         {
   1718 	  typedef typename __make_1st_indices<_Tpls...>::__type __idx;
   1719 	  typedef __tuple_concater<_Ret, __idx, _Tpls...>      __next;
   1720 	  return __next::_S_do(std::forward<_Tpls>(__tps)...,
   1721 			       std::forward<_Us>(__us)...,
   1722 			       std::get<_Is>(std::forward<_Tp>(__tp))...);
   1723 	}
   1724     };
   1725 
   1726   template<typename _Ret>
   1727     struct __tuple_concater<_Ret, _Index_tuple<>>
   1728     {
   1729       template<typename... _Us>
   1730 	static constexpr _Ret
   1731 	_S_do(_Us&&... __us)
   1732         {
   1733 	  return _Ret(std::forward<_Us>(__us)...);
   1734 	}
   1735     };
   1736 
   1737   template<typename... _Tps>
   1738     struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
   1739     { };
   1740   /// @endcond
   1741 
   1742   /// Create a `tuple` containing all elements from multiple tuple-like objects
   1743   template<typename... _Tpls, typename = typename
   1744            enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
   1745     constexpr auto
   1746     tuple_cat(_Tpls&&... __tpls)
   1747     -> typename __tuple_cat_result<_Tpls...>::__type
   1748     {
   1749       typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
   1750       typedef typename __make_1st_indices<_Tpls...>::__type __idx;
   1751       typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
   1752       return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
   1753     }
   1754 
   1755   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   1756   // 2301. Why is tie not constexpr?
   1757   /// Return a tuple of lvalue references bound to the arguments
   1758   template<typename... _Elements>
   1759     constexpr tuple<_Elements&...>
   1760     tie(_Elements&... __args) noexcept
   1761     { return tuple<_Elements&...>(__args...); }
   1762 
   1763   /// Exchange the values of two tuples
   1764   template<typename... _Elements>
   1765     _GLIBCXX20_CONSTEXPR
   1766     inline
   1767 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
   1768     // Constrained free swap overload, see p0185r1
   1769     typename enable_if<__and_<__is_swappable<_Elements>...>::value
   1770       >::type
   1771 #else
   1772     void
   1773 #endif
   1774     swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
   1775     noexcept(noexcept(__x.swap(__y)))
   1776     { __x.swap(__y); }
   1777 
   1778 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
   1779   /// Exchange the values of two const tuples (if const elements can be swapped)
   1780   template<typename... _Elements>
   1781     _GLIBCXX20_CONSTEXPR
   1782     typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
   1783     swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
   1784 #endif
   1785 
   1786   // A class (and instance) which can be used in 'tie' when an element
   1787   // of a tuple is not required.
   1788   // _GLIBCXX14_CONSTEXPR
   1789   // 2933. PR for LWG 2773 could be clearer
   1790   struct _Swallow_assign
   1791   {
   1792     template<class _Tp>
   1793       _GLIBCXX14_CONSTEXPR const _Swallow_assign&
   1794       operator=(const _Tp&) const
   1795       { return *this; }
   1796   };
   1797 
   1798   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   1799   // 2773. Making std::ignore constexpr
   1800   /** Used with `std::tie` to ignore an element of a tuple
   1801    *
   1802    * When using `std::tie` to assign the elements of a tuple to variables,
   1803    * unwanted elements can be ignored by using `std::ignore`. For example:
   1804    *
   1805    * ```
   1806    * int x, y;
   1807    * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
   1808    * ```
   1809    *
   1810    * This assignment will perform `x=1; std::ignore=2; y=3;` which results
   1811    * in the second element being ignored.
   1812    *
   1813    * @since C++11
   1814    */
   1815   _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
   1816 
   1817   /// Partial specialization for tuples
   1818   template<typename... _Types, typename _Alloc>
   1819     struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
   1820 
   1821   // See stl_pair.h...
   1822   /** "piecewise construction" using a tuple of arguments for each member.
   1823    *
   1824    * @param __first Arguments for the first member of the pair.
   1825    * @param __second Arguments for the second member of the pair.
   1826    *
   1827    * The elements of each tuple will be used as the constructor arguments
   1828    * for the data members of the pair.
   1829   */
   1830   template<class _T1, class _T2>
   1831     template<typename... _Args1, typename... _Args2>
   1832       _GLIBCXX20_CONSTEXPR
   1833       inline
   1834       pair<_T1, _T2>::
   1835       pair(piecewise_construct_t,
   1836 	   tuple<_Args1...> __first, tuple<_Args2...> __second)
   1837       : pair(__first, __second,
   1838 	     typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
   1839 	     typename _Build_index_tuple<sizeof...(_Args2)>::__type())
   1840       { }
   1841 
   1842   template<class _T1, class _T2>
   1843     template<typename... _Args1, size_t... _Indexes1,
   1844 	     typename... _Args2, size_t... _Indexes2>
   1845       _GLIBCXX20_CONSTEXPR inline
   1846       pair<_T1, _T2>::
   1847       pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
   1848 	   _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
   1849       : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
   1850 	second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
   1851       { }
   1852 
   1853 #if __cplusplus >= 201703L
   1854 
   1855   // Unpack a std::tuple into a type trait and use its value.
   1856   // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
   1857   // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
   1858   // Otherwise the result is false (because we don't know if std::get throws).
   1859   template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
   1860     inline constexpr bool __unpack_std_tuple = false;
   1861 
   1862   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
   1863     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
   1864       = _Trait<_Tp, _Up...>::value;
   1865 
   1866   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
   1867     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
   1868       = _Trait<_Tp, _Up&...>::value;
   1869 
   1870   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
   1871     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
   1872       = _Trait<_Tp, const _Up...>::value;
   1873 
   1874   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
   1875     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
   1876       = _Trait<_Tp, const _Up&...>::value;
   1877 
   1878 # define __cpp_lib_apply 201603L
   1879 
   1880   template <typename _Fn, typename _Tuple, size_t... _Idx>
   1881     constexpr decltype(auto)
   1882     __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
   1883     {
   1884       return std::__invoke(std::forward<_Fn>(__f),
   1885 			   std::get<_Idx>(std::forward<_Tuple>(__t))...);
   1886     }
   1887 
   1888   template <typename _Fn, typename _Tuple>
   1889     constexpr decltype(auto)
   1890     apply(_Fn&& __f, _Tuple&& __t)
   1891     noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
   1892     {
   1893       using _Indices
   1894 	= make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
   1895       return std::__apply_impl(std::forward<_Fn>(__f),
   1896 			       std::forward<_Tuple>(__t),
   1897 			       _Indices{});
   1898     }
   1899 
   1900 #define __cpp_lib_make_from_tuple  201606L
   1901 
   1902   template <typename _Tp, typename _Tuple, size_t... _Idx>
   1903     constexpr _Tp
   1904     __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
   1905     { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
   1906 
   1907   template <typename _Tp, typename _Tuple>
   1908     constexpr _Tp
   1909     make_from_tuple(_Tuple&& __t)
   1910     noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
   1911     {
   1912       return __make_from_tuple_impl<_Tp>(
   1913         std::forward<_Tuple>(__t),
   1914 	make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>{});
   1915     }
   1916 #endif // C++17
   1917 
   1918   /// @}
   1919 
   1920 _GLIBCXX_END_NAMESPACE_VERSION
   1921 } // namespace std
   1922 
   1923 #endif // C++11
   1924 
   1925 #endif // _GLIBCXX_TUPLE
   1926