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