xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/std/tuple (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
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
47namespace 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