]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/include/std/tuple
tuple (__conv_types, [...]): Remove.
[thirdparty/gcc.git] / libstdc++-v3 / include / std / tuple
1 // <tuple> -*- C++ -*-
2
3 // Copyright (C) 2007, 2008, 2009, 2010, 2011 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 #ifndef __GXX_EXPERIMENTAL_CXX0X__
35 # include <bits/c++0x_warning.h>
36 #else
37
38 #include <utility>
39 #include <bits/uses_allocator.h>
40
41 namespace std _GLIBCXX_VISIBILITY(default)
42 {
43 _GLIBCXX_BEGIN_NAMESPACE_VERSION
44
45 // Adds a const reference to a non-reference type.
46 template<typename _Tp>
47 struct __add_c_ref
48 { typedef const _Tp& type; };
49
50 template<typename _Tp>
51 struct __add_c_ref<_Tp&>
52 { typedef _Tp& type; };
53
54 // Adds a reference to a non-reference type.
55 template<typename _Tp>
56 struct __add_ref
57 { typedef _Tp& type; };
58
59 template<typename _Tp>
60 struct __add_ref<_Tp&>
61 { typedef _Tp& type; };
62
63 // Adds an rvalue reference to a non-reference type.
64 template<typename _Tp>
65 struct __add_r_ref
66 { typedef _Tp&& type; };
67
68 template<typename _Tp>
69 struct __add_r_ref<_Tp&>
70 { typedef _Tp& type; };
71
72 template<std::size_t _Idx, typename _Head, bool _IsEmpty>
73 struct _Head_base;
74
75 template<std::size_t _Idx, typename _Head>
76 struct _Head_base<_Idx, _Head, true>
77 : public _Head
78 {
79 constexpr _Head_base()
80 : _Head() { }
81
82 constexpr _Head_base(const _Head& __h)
83 : _Head(__h) { }
84
85 template<typename _UHead, typename = typename
86 enable_if<!is_convertible<_UHead,
87 __uses_alloc_base>::value>::type>
88 constexpr _Head_base(_UHead&& __h)
89 : _Head(std::forward<_UHead>(__h)) { }
90
91 _Head_base(__uses_alloc0)
92 : _Head() { }
93
94 template<typename _Alloc>
95 _Head_base(__uses_alloc1<_Alloc> __a)
96 : _Head(allocator_arg, *__a._M_a) { }
97
98 template<typename _Alloc>
99 _Head_base(__uses_alloc2<_Alloc> __a)
100 : _Head(*__a._M_a) { }
101
102 template<typename _UHead>
103 _Head_base(__uses_alloc0, _UHead&& __uhead)
104 : _Head(std::forward<_UHead>(__uhead)) { }
105
106 template<typename _Alloc, typename _UHead>
107 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
108 : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
109
110 template<typename _Alloc, typename _UHead>
111 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
112 : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
113
114 static constexpr _Head&
115 _M_head(_Head_base& __b) noexcept { return __b; }
116
117 static constexpr const _Head&
118 _M_head(const _Head_base& __b) noexcept { return __b; }
119 };
120
121 template<std::size_t _Idx, typename _Head>
122 struct _Head_base<_Idx, _Head, false>
123 {
124 constexpr _Head_base()
125 : _M_head_impl() { }
126
127 constexpr _Head_base(const _Head& __h)
128 : _M_head_impl(__h) { }
129
130 template<typename _UHead, typename = typename
131 enable_if<!is_convertible<_UHead,
132 __uses_alloc_base>::value>::type>
133 constexpr _Head_base(_UHead&& __h)
134 : _M_head_impl(std::forward<_UHead>(__h)) { }
135
136 _Head_base(__uses_alloc0)
137 : _M_head_impl() { }
138
139 template<typename _Alloc>
140 _Head_base(__uses_alloc1<_Alloc> __a)
141 : _M_head_impl(allocator_arg, *__a._M_a) { }
142
143 template<typename _Alloc>
144 _Head_base(__uses_alloc2<_Alloc> __a)
145 : _M_head_impl(*__a._M_a) { }
146
147 template<typename _UHead>
148 _Head_base(__uses_alloc0, _UHead&& __uhead)
149 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
150
151 template<typename _Alloc, typename _UHead>
152 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
153 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
154 { }
155
156 template<typename _Alloc, typename _UHead>
157 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
158 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
159
160 static constexpr _Head&
161 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
162
163 static constexpr const _Head&
164 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
165
166 _Head _M_head_impl;
167 };
168
169 /**
170 * Contains the actual implementation of the @c tuple template, stored
171 * as a recursive inheritance hierarchy from the first element (most
172 * derived class) to the last (least derived class). The @c Idx
173 * parameter gives the 0-based index of the element stored at this
174 * point in the hierarchy; we use it to implement a constant-time
175 * get() operation.
176 */
177 template<std::size_t _Idx, typename... _Elements>
178 struct _Tuple_impl;
179
180 /**
181 * Zero-element tuple implementation. This is the basis case for the
182 * inheritance recursion.
183 */
184 template<std::size_t _Idx>
185 struct _Tuple_impl<_Idx>
186 {
187 template<std::size_t, typename...> friend class _Tuple_impl;
188
189 _Tuple_impl() = default;
190
191 template<typename _Alloc>
192 _Tuple_impl(allocator_arg_t, const _Alloc&) { }
193
194 template<typename _Alloc>
195 _Tuple_impl(allocator_arg_t, const _Alloc&, const _Tuple_impl&) { }
196
197 template<typename _Alloc>
198 _Tuple_impl(allocator_arg_t, const _Alloc&, _Tuple_impl&&) { }
199
200 protected:
201 void _M_swap(_Tuple_impl&) noexcept { /* no-op */ }
202 };
203
204 /**
205 * Recursive tuple implementation. Here we store the @c Head element
206 * and derive from a @c Tuple_impl containing the remaining elements
207 * (which contains the @c Tail).
208 */
209 template<std::size_t _Idx, typename _Head, typename... _Tail>
210 struct _Tuple_impl<_Idx, _Head, _Tail...>
211 : public _Tuple_impl<_Idx + 1, _Tail...>,
212 private _Head_base<_Idx, _Head, std::is_empty<_Head>::value>
213 {
214 template<std::size_t, typename...> friend class _Tuple_impl;
215
216 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
217 typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base;
218
219 static constexpr _Head&
220 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
221
222 static constexpr const _Head&
223 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
224
225 static constexpr _Inherited&
226 _M_tail(_Tuple_impl& __t) noexcept { return __t; }
227
228 static constexpr const _Inherited&
229 _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
230
231 constexpr _Tuple_impl()
232 : _Inherited(), _Base() { }
233
234 explicit
235 constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail)
236 : _Inherited(__tail...), _Base(__head) { }
237
238 template<typename _UHead, typename... _UTail, typename = typename
239 enable_if<sizeof...(_Tail) == sizeof...(_UTail)>::type>
240 explicit
241 constexpr _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
242 : _Inherited(std::forward<_UTail>(__tail)...),
243 _Base(std::forward<_UHead>(__head)) { }
244
245 constexpr _Tuple_impl(const _Tuple_impl&) = default;
246
247 constexpr
248 _Tuple_impl(_Tuple_impl&& __in)
249 noexcept(__and_<is_nothrow_move_constructible<_Head>,
250 is_nothrow_move_constructible<_Inherited>>::value)
251 : _Inherited(std::move(_M_tail(__in))),
252 _Base(std::forward<_Head>(_M_head(__in))) { }
253
254 template<typename... _UElements>
255 constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
256 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
257 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { }
258
259 template<typename _UHead, typename... _UTails>
260 constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
261 : _Inherited(std::move
262 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
263 _Base(std::forward<_UHead>
264 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { }
265
266 template<typename _Alloc>
267 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
268 : _Inherited(__tag, __a),
269 _Base(__use_alloc<_Head>(__a)) { }
270
271 template<typename _Alloc>
272 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
273 const _Head& __head, const _Tail&... __tail)
274 : _Inherited(__tag, __a, __tail...),
275 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { }
276
277 template<typename _Alloc, typename _UHead, typename... _UTail,
278 typename = typename enable_if<sizeof...(_Tail)
279 == sizeof...(_UTail)>::type>
280 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
281 _UHead&& __head, _UTail&&... __tail)
282 : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
283 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
284 std::forward<_UHead>(__head)) { }
285
286 template<typename _Alloc>
287 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
288 const _Tuple_impl& __in)
289 : _Inherited(__tag, __a, _M_tail(__in)),
290 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { }
291
292 template<typename _Alloc>
293 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
294 _Tuple_impl&& __in)
295 : _Inherited(__tag, __a, std::move(_M_tail(__in))),
296 _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
297 std::forward<_Head>(_M_head(__in))) { }
298
299 template<typename _Alloc, typename... _UElements>
300 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
301 const _Tuple_impl<_Idx, _UElements...>& __in)
302 : _Inherited(__tag, __a,
303 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
304 _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
305 _Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { }
306
307 template<typename _Alloc, typename _UHead, typename... _UTails>
308 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
309 _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
310 : _Inherited(__tag, __a, std::move
311 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
312 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
313 std::forward<_UHead>
314 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { }
315
316 _Tuple_impl&
317 operator=(const _Tuple_impl& __in)
318 {
319 _M_head(*this) = _M_head(__in);
320 _M_tail(*this) = _M_tail(__in);
321 return *this;
322 }
323
324 _Tuple_impl&
325 operator=(_Tuple_impl&& __in)
326 noexcept(__and_<is_nothrow_move_assignable<_Head>,
327 is_nothrow_move_assignable<_Inherited>>::value)
328 {
329 _M_head(*this) = std::forward<_Head>(_M_head(__in));
330 _M_tail(*this) = std::move(_M_tail(__in));
331 return *this;
332 }
333
334 template<typename... _UElements>
335 _Tuple_impl&
336 operator=(const _Tuple_impl<_Idx, _UElements...>& __in)
337 {
338 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
339 _M_tail(*this) = _Tuple_impl<_Idx, _UElements...>::_M_tail(__in);
340 return *this;
341 }
342
343 template<typename _UHead, typename... _UTails>
344 _Tuple_impl&
345 operator=(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
346 {
347 _M_head(*this) = std::forward<_UHead>
348 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
349 _M_tail(*this) = std::move
350 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in));
351 return *this;
352 }
353
354 protected:
355 void
356 _M_swap(_Tuple_impl& __in)
357 noexcept(noexcept(swap(std::declval<_Head&>(),
358 std::declval<_Head&>()))
359 && noexcept(_M_tail(__in)._M_swap(_M_tail(__in))))
360 {
361 using std::swap;
362 swap(_M_head(*this), _M_head(__in));
363 _Inherited::_M_swap(_M_tail(__in));
364 }
365 };
366
367 /// Primary class template, tuple
368 template<typename... _Elements>
369 class tuple : public _Tuple_impl<0, _Elements...>
370 {
371 typedef _Tuple_impl<0, _Elements...> _Inherited;
372
373 public:
374 constexpr tuple()
375 : _Inherited() { }
376
377 explicit
378 constexpr tuple(const _Elements&... __elements)
379 : _Inherited(__elements...) { }
380
381 template<typename... _UElements, typename = typename
382 enable_if<__and_<is_convertible<_UElements,
383 _Elements>...>::value>::type>
384 explicit
385 constexpr tuple(_UElements&&... __elements)
386 : _Inherited(std::forward<_UElements>(__elements)...) { }
387
388 constexpr tuple(const tuple&) = default;
389
390 constexpr tuple(tuple&&) = default;
391
392 template<typename... _UElements, typename = typename
393 enable_if<__and_<is_convertible<const _UElements&,
394 _Elements>...>::value>::type>
395 constexpr tuple(const tuple<_UElements...>& __in)
396 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
397 { }
398
399 template<typename... _UElements, typename = typename
400 enable_if<__and_<is_convertible<_UElements,
401 _Elements>...>::value>::type>
402 constexpr tuple(tuple<_UElements...>&& __in)
403 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
404
405 // Allocator-extended constructors.
406
407 template<typename _Alloc>
408 tuple(allocator_arg_t __tag, const _Alloc& __a)
409 : _Inherited(__tag, __a) { }
410
411 template<typename _Alloc>
412 tuple(allocator_arg_t __tag, const _Alloc& __a,
413 const _Elements&... __elements)
414 : _Inherited(__tag, __a, __elements...) { }
415
416 template<typename _Alloc, typename... _UElements, typename = typename
417 enable_if<sizeof...(_UElements)
418 == sizeof...(_Elements)>::type>
419 tuple(allocator_arg_t __tag, const _Alloc& __a,
420 _UElements&&... __elements)
421 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
422 { }
423
424 template<typename _Alloc>
425 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
426 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
427
428 template<typename _Alloc>
429 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
430 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
431
432 template<typename _Alloc, typename... _UElements, typename = typename
433 enable_if<sizeof...(_UElements)
434 == sizeof...(_Elements)>::type>
435 tuple(allocator_arg_t __tag, const _Alloc& __a,
436 const tuple<_UElements...>& __in)
437 : _Inherited(__tag, __a,
438 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
439 { }
440
441 template<typename _Alloc, typename... _UElements, typename = typename
442 enable_if<sizeof...(_UElements)
443 == sizeof...(_Elements)>::type>
444 tuple(allocator_arg_t __tag, const _Alloc& __a,
445 tuple<_UElements...>&& __in)
446 : _Inherited(__tag, __a,
447 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
448 { }
449
450 tuple&
451 operator=(const tuple& __in)
452 {
453 static_cast<_Inherited&>(*this) = __in;
454 return *this;
455 }
456
457 tuple&
458 operator=(tuple&& __in)
459 noexcept(is_nothrow_move_assignable<_Inherited>::value)
460 {
461 static_cast<_Inherited&>(*this) = std::move(__in);
462 return *this;
463 }
464
465 template<typename... _UElements, typename = typename
466 enable_if<sizeof...(_UElements)
467 == sizeof...(_Elements)>::type>
468 tuple&
469 operator=(const tuple<_UElements...>& __in)
470 {
471 static_cast<_Inherited&>(*this) = __in;
472 return *this;
473 }
474
475 template<typename... _UElements, typename = typename
476 enable_if<sizeof...(_UElements)
477 == sizeof...(_Elements)>::type>
478 tuple&
479 operator=(tuple<_UElements...>&& __in)
480 {
481 static_cast<_Inherited&>(*this) = std::move(__in);
482 return *this;
483 }
484
485 void
486 swap(tuple& __in)
487 noexcept(noexcept(__in._M_swap(__in)))
488 { _Inherited::_M_swap(__in); }
489 };
490
491 // Explicit specialization, zero-element tuple.
492 template<>
493 class tuple<>
494 {
495 public:
496 void swap(tuple&) noexcept { /* no-op */ }
497 };
498
499 /// Partial specialization, 2-element tuple.
500 /// Includes construction and assignment from a pair.
501 template<typename _T1, typename _T2>
502 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
503 {
504 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
505
506 public:
507 constexpr tuple()
508 : _Inherited() { }
509
510 explicit
511 constexpr tuple(const _T1& __a1, const _T2& __a2)
512 : _Inherited(__a1, __a2) { }
513
514 template<typename _U1, typename _U2, typename = typename
515 enable_if<__and_<is_convertible<_U1, _T1>,
516 is_convertible<_U2, _T2>>::value>::type>
517 explicit
518 constexpr tuple(_U1&& __a1, _U2&& __a2)
519 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
520
521 constexpr tuple(const tuple&) = default;
522
523 constexpr tuple(tuple&&) = default;
524
525 template<typename _U1, typename _U2, typename = typename
526 enable_if<__and_<is_convertible<const _U1&, _T1>,
527 is_convertible<const _U2&, _T2>>::value>::type>
528 constexpr tuple(const tuple<_U1, _U2>& __in)
529 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
530
531 template<typename _U1, typename _U2, typename = typename
532 enable_if<__and_<is_convertible<_U1, _T1>,
533 is_convertible<_U2, _T2>>::value>::type>
534 constexpr tuple(tuple<_U1, _U2>&& __in)
535 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
536
537 template<typename _U1, typename _U2, typename = typename
538 enable_if<__and_<is_convertible<const _U1&, _T1>,
539 is_convertible<const _U2&, _T2>>::value>::type>
540 constexpr tuple(const pair<_U1, _U2>& __in)
541 : _Inherited(__in.first, __in.second) { }
542
543 template<typename _U1, typename _U2, typename = typename
544 enable_if<__and_<is_convertible<_U1, _T1>,
545 is_convertible<_U2, _T2>>::value>::type>
546 constexpr tuple(pair<_U1, _U2>&& __in)
547 : _Inherited(std::forward<_U1>(__in.first),
548 std::forward<_U2>(__in.second)) { }
549
550 // Allocator-extended constructors.
551
552 template<typename _Alloc>
553 tuple(allocator_arg_t __tag, const _Alloc& __a)
554 : _Inherited(__tag, __a) { }
555
556 template<typename _Alloc>
557 tuple(allocator_arg_t __tag, const _Alloc& __a,
558 const _T1& __a1, const _T2& __a2)
559 : _Inherited(__tag, __a, __a1, __a2) { }
560
561 template<typename _Alloc, typename _U1, typename _U2>
562 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
563 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
564 std::forward<_U2>(__a2)) { }
565
566 template<typename _Alloc>
567 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
568 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
569
570 template<typename _Alloc>
571 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
572 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
573
574 template<typename _Alloc, typename _U1, typename _U2>
575 tuple(allocator_arg_t __tag, const _Alloc& __a,
576 const tuple<_U1, _U2>& __in)
577 : _Inherited(__tag, __a,
578 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
579 { }
580
581 template<typename _Alloc, typename _U1, typename _U2>
582 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
583 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
584 { }
585
586 template<typename _Alloc, typename _U1, typename _U2>
587 tuple(allocator_arg_t __tag, const _Alloc& __a,
588 const pair<_U1, _U2>& __in)
589 : _Inherited(__tag, __a, __in.first, __in.second) { }
590
591 template<typename _Alloc, typename _U1, typename _U2>
592 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
593 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
594 std::forward<_U2>(__in.second)) { }
595
596 tuple&
597 operator=(const tuple& __in)
598 {
599 static_cast<_Inherited&>(*this) = __in;
600 return *this;
601 }
602
603 tuple&
604 operator=(tuple&& __in)
605 noexcept(is_nothrow_move_assignable<_Inherited>::value)
606 {
607 static_cast<_Inherited&>(*this) = std::move(__in);
608 return *this;
609 }
610
611 template<typename _U1, typename _U2>
612 tuple&
613 operator=(const tuple<_U1, _U2>& __in)
614 {
615 static_cast<_Inherited&>(*this) = __in;
616 return *this;
617 }
618
619 template<typename _U1, typename _U2>
620 tuple&
621 operator=(tuple<_U1, _U2>&& __in)
622 {
623 static_cast<_Inherited&>(*this) = std::move(__in);
624 return *this;
625 }
626
627 template<typename _U1, typename _U2>
628 tuple&
629 operator=(const pair<_U1, _U2>& __in)
630 {
631 this->_M_head(*this) = __in.first;
632 this->_M_tail(*this)._M_head(*this) = __in.second;
633 return *this;
634 }
635
636 template<typename _U1, typename _U2>
637 tuple&
638 operator=(pair<_U1, _U2>&& __in)
639 {
640 this->_M_head(*this) = std::forward<_U1>(__in.first);
641 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
642 return *this;
643 }
644
645 void
646 swap(tuple& __in)
647 noexcept(noexcept(__in._M_swap(__in)))
648 { _Inherited::_M_swap(__in); }
649 };
650
651
652 /// Gives the type of the ith element of a given tuple type.
653 template<std::size_t __i, typename _Tp>
654 struct tuple_element;
655
656 /**
657 * Recursive case for tuple_element: strip off the first element in
658 * the tuple and retrieve the (i-1)th element of the remaining tuple.
659 */
660 template<std::size_t __i, typename _Head, typename... _Tail>
661 struct tuple_element<__i, tuple<_Head, _Tail...> >
662 : tuple_element<__i - 1, tuple<_Tail...> > { };
663
664 /**
665 * Basis case for tuple_element: The first element is the one we're seeking.
666 */
667 template<typename _Head, typename... _Tail>
668 struct tuple_element<0, tuple<_Head, _Tail...> >
669 {
670 typedef _Head type;
671 };
672
673 template<std::size_t __i, typename _Tp>
674 struct tuple_element<__i, const _Tp>
675 {
676 typedef typename
677 add_const<typename tuple_element<__i, _Tp>::type>::type type;
678 };
679
680 template<std::size_t __i, typename _Tp>
681 struct tuple_element<__i, volatile _Tp>
682 {
683 typedef typename
684 add_volatile<typename tuple_element<__i, _Tp>::type>::type type;
685 };
686
687 template<std::size_t __i, typename _Tp>
688 struct tuple_element<__i, const volatile _Tp>
689 {
690 typedef typename
691 add_cv<typename tuple_element<__i, _Tp>::type>::type type;
692 };
693
694 /// Finds the size of a given tuple type.
695 template<typename _Tp>
696 struct tuple_size;
697
698 template<typename _Tp>
699 struct tuple_size<const _Tp>
700 : public integral_constant<
701 typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
702 tuple_size<_Tp>::value> { };
703
704 template<typename _Tp>
705 struct tuple_size<volatile _Tp>
706 : public integral_constant<
707 typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
708 tuple_size<_Tp>::value> { };
709
710 template<typename _Tp>
711 struct tuple_size<const volatile _Tp>
712 : public integral_constant<
713 typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
714 tuple_size<_Tp>::value> { };
715
716 /// class tuple_size
717 template<typename... _Elements>
718 struct tuple_size<tuple<_Elements...>>
719 : public integral_constant<std::size_t, sizeof...(_Elements)> { };
720
721 template<std::size_t __i, typename _Head, typename... _Tail>
722 constexpr typename __add_ref<_Head>::type
723 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
724 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
725
726 template<std::size_t __i, typename _Head, typename... _Tail>
727 constexpr typename __add_c_ref<_Head>::type
728 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
729 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
730
731 // Return a reference (const reference, rvalue reference) to the ith element
732 // of a tuple. Any const or non-const ref elements are returned with their
733 // original type.
734 template<std::size_t __i, typename... _Elements>
735 constexpr typename __add_ref<
736 typename tuple_element<__i, tuple<_Elements...>>::type
737 >::type
738 get(tuple<_Elements...>& __t) noexcept
739 { return __get_helper<__i>(__t); }
740
741 template<std::size_t __i, typename... _Elements>
742 constexpr typename __add_c_ref<
743 typename tuple_element<__i, tuple<_Elements...>>::type
744 >::type
745 get(const tuple<_Elements...>& __t) noexcept
746 { return __get_helper<__i>(__t); }
747
748 template<std::size_t __i, typename... _Elements>
749 constexpr typename __add_r_ref<
750 typename tuple_element<__i, tuple<_Elements...>>::type
751 >::type
752 get(tuple<_Elements...>&& __t) noexcept
753 { return std::forward<typename tuple_element<__i,
754 tuple<_Elements...>>::type&&>(get<__i>(__t)); }
755
756 // This class helps construct the various comparison operations on tuples
757 template<std::size_t __check_equal_size, std::size_t __i, std::size_t __j,
758 typename _Tp, typename _Up>
759 struct __tuple_compare;
760
761 template<std::size_t __i, std::size_t __j, typename _Tp, typename _Up>
762 struct __tuple_compare<0, __i, __j, _Tp, _Up>
763 {
764 static bool
765 __eq(const _Tp& __t, const _Up& __u)
766 {
767 return (get<__i>(__t) == get<__i>(__u) &&
768 __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__eq(__t, __u));
769 }
770
771 static bool
772 __less(const _Tp& __t, const _Up& __u)
773 {
774 return ((get<__i>(__t) < get<__i>(__u))
775 || !(get<__i>(__u) < get<__i>(__t)) &&
776 __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__less(__t, __u));
777 }
778 };
779
780 template<std::size_t __i, typename _Tp, typename _Up>
781 struct __tuple_compare<0, __i, __i, _Tp, _Up>
782 {
783 static bool
784 __eq(const _Tp&, const _Up&) { return true; }
785
786 static bool
787 __less(const _Tp&, const _Up&) { return false; }
788 };
789
790 template<typename... _TElements, typename... _UElements>
791 bool
792 operator==(const tuple<_TElements...>& __t,
793 const tuple<_UElements...>& __u)
794 {
795 typedef tuple<_TElements...> _Tp;
796 typedef tuple<_UElements...> _Up;
797 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value,
798 0, tuple_size<_Tp>::value, _Tp, _Up>::__eq(__t, __u));
799 }
800
801 template<typename... _TElements, typename... _UElements>
802 bool
803 operator<(const tuple<_TElements...>& __t,
804 const tuple<_UElements...>& __u)
805 {
806 typedef tuple<_TElements...> _Tp;
807 typedef tuple<_UElements...> _Up;
808 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value,
809 0, tuple_size<_Tp>::value, _Tp, _Up>::__less(__t, __u));
810 }
811
812 template<typename... _TElements, typename... _UElements>
813 inline bool
814 operator!=(const tuple<_TElements...>& __t,
815 const tuple<_UElements...>& __u)
816 { return !(__t == __u); }
817
818 template<typename... _TElements, typename... _UElements>
819 inline bool
820 operator>(const tuple<_TElements...>& __t,
821 const tuple<_UElements...>& __u)
822 { return __u < __t; }
823
824 template<typename... _TElements, typename... _UElements>
825 inline bool
826 operator<=(const tuple<_TElements...>& __t,
827 const tuple<_UElements...>& __u)
828 { return !(__u < __t); }
829
830 template<typename... _TElements, typename... _UElements>
831 inline bool
832 operator>=(const tuple<_TElements...>& __t,
833 const tuple<_UElements...>& __u)
834 { return !(__t < __u); }
835
836 // NB: DR 705.
837 template<typename... _Elements>
838 constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
839 make_tuple(_Elements&&... __args)
840 {
841 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
842 __result_type;
843 return __result_type(std::forward<_Elements>(__args)...);
844 }
845
846 template<typename... _Elements>
847 constexpr tuple<_Elements&&...>
848 forward_as_tuple(_Elements&&... __args) noexcept
849 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
850
851
852 template<typename, std::size_t> struct array;
853
854 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
855 constexpr _Tp& get(array<_Tp, _Nm>&) noexcept;
856
857 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
858 constexpr _Tp&& get(array<_Tp, _Nm>&&) noexcept;
859
860 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
861 constexpr const _Tp& get(const array<_Tp, _Nm>&) noexcept;
862
863 template<typename>
864 struct __is_tuple_like_impl : false_type
865 { };
866
867 template<typename... _Tps>
868 struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
869 { };
870
871 template<typename _T1, typename _T2>
872 struct __is_tuple_like_impl<pair<_T1, _T2>> : true_type
873 { };
874
875 template<typename _Tp, std::size_t _Nm>
876 struct __is_tuple_like_impl<array<_Tp, _Nm>> : true_type
877 { };
878
879 // Internal type trait that allows us to sfinae-protect tuple_cat.
880 template<typename _Tp>
881 struct __is_tuple_like
882 : public __is_tuple_like_impl<typename std::remove_cv
883 <typename std::remove_reference<_Tp>::type>::type>::type
884 { };
885
886 // Stores a tuple of indices. Also used by bind() to extract the elements
887 // in a tuple.
888 template<std::size_t... _Indexes>
889 struct _Index_tuple
890 {
891 typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next;
892 };
893
894 // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
895 template<std::size_t _Num>
896 struct _Build_index_tuple
897 {
898 typedef typename _Build_index_tuple<_Num - 1>::__type::__next __type;
899 };
900
901 template<>
902 struct _Build_index_tuple<0>
903 {
904 typedef _Index_tuple<> __type;
905 };
906
907 template<std::size_t, typename, typename, std::size_t>
908 struct __make_tuple_impl;
909
910 template<std::size_t _Idx, typename _Tuple, typename... _Tp,
911 std::size_t _Nm>
912 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
913 {
914 typedef typename __make_tuple_impl<_Idx + 1, tuple<_Tp...,
915 typename std::tuple_element<_Idx, _Tuple>::type>, _Tuple, _Nm>::__type
916 __type;
917 };
918
919 template<std::size_t _Nm, typename _Tuple, typename... _Tp>
920 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
921 {
922 typedef tuple<_Tp...> __type;
923 };
924
925 template<typename _Tuple>
926 struct __do_make_tuple
927 : public __make_tuple_impl<0, tuple<>, _Tuple,
928 std::tuple_size<_Tuple>::value>
929 { };
930
931 // Returns the std::tuple equivalent of a tuple-like type.
932 template<typename _Tuple>
933 struct __make_tuple
934 : public __do_make_tuple<typename std::remove_cv
935 <typename std::remove_reference<_Tuple>::type>::type>
936 { };
937
938 // Combines several std::tuple's into a single one.
939 template<typename...>
940 struct __combine_tuples;
941
942 template<>
943 struct __combine_tuples<>
944 {
945 typedef tuple<> __type;
946 };
947
948 template<typename... _Ts>
949 struct __combine_tuples<tuple<_Ts...>>
950 {
951 typedef tuple<_Ts...> __type;
952 };
953
954 template<typename... _T1s, typename... _T2s, typename... _Rem>
955 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
956 {
957 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
958 _Rem...>::__type __type;
959 };
960
961 // Computes the result type of tuple_cat given a set of tuple-like types.
962 template<typename... _Tpls>
963 struct __tuple_cat_result
964 {
965 typedef typename __combine_tuples
966 <typename __make_tuple<_Tpls>::__type...>::__type __type;
967 };
968
969 // Helper to determine the index set for the first tuple-like
970 // type of a given set.
971 template<typename...>
972 struct __make_1st_indices;
973
974 template<>
975 struct __make_1st_indices<>
976 {
977 typedef std::_Index_tuple<> __type;
978 };
979
980 template<typename _Tp, typename... _Tpls>
981 struct __make_1st_indices<_Tp, _Tpls...>
982 {
983 typedef typename std::_Build_index_tuple<std::tuple_size<
984 typename std::remove_reference<_Tp>::type>::value>::__type __type;
985 };
986
987 // Performs the actual concatenation by step-wise expanding tuple-like
988 // objects into the elements, which are finally forwarded into the
989 // result tuple.
990 template<typename _Ret, typename _Indices, typename... _Tpls>
991 struct __tuple_concater;
992
993 template<typename _Ret, std::size_t... _Is, typename _Tp, typename... _Tpls>
994 struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...>
995 {
996 template<typename... _Us>
997 static constexpr _Ret
998 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
999 {
1000 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
1001 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
1002 return __next::_S_do(std::forward<_Tpls>(__tps)...,
1003 std::forward<_Us>(__us)...,
1004 std::get<_Is>(std::forward<_Tp>(__tp))...);
1005 }
1006 };
1007
1008 template<typename _Ret>
1009 struct __tuple_concater<_Ret, std::_Index_tuple<>>
1010 {
1011 template<typename... _Us>
1012 static constexpr _Ret
1013 _S_do(_Us&&... __us)
1014 {
1015 return _Ret(std::forward<_Us>(__us)...);
1016 }
1017 };
1018
1019 template<typename... _Tpls, typename = typename
1020 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
1021 constexpr auto
1022 tuple_cat(_Tpls&&... __tpls)
1023 -> typename __tuple_cat_result<_Tpls...>::__type
1024 {
1025 typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
1026 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
1027 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
1028 return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
1029 }
1030
1031 template<typename... _Elements>
1032 inline tuple<_Elements&...>
1033 tie(_Elements&... __args) noexcept
1034 { return tuple<_Elements&...>(__args...); }
1035
1036 template<typename... _Elements>
1037 inline void
1038 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
1039 noexcept(noexcept(__x.swap(__y)))
1040 { __x.swap(__y); }
1041
1042 // A class (and instance) which can be used in 'tie' when an element
1043 // of a tuple is not required
1044 struct _Swallow_assign
1045 {
1046 template<class _Tp>
1047 const _Swallow_assign&
1048 operator=(const _Tp&) const
1049 { return *this; }
1050 };
1051
1052 const _Swallow_assign ignore{};
1053
1054 /// Partial specialization for tuples
1055 template<typename... _Types, typename _Alloc>
1056 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
1057
1058 // See stl_pair.h...
1059 template<class _T1, class _T2>
1060 template<typename _Tp, typename... _Args>
1061 inline _Tp
1062 pair<_T1, _T2>::__cons(tuple<_Args...>&& __tuple)
1063 {
1064 typedef typename _Build_index_tuple<sizeof...(_Args)>::__type
1065 _Indexes;
1066 return __do_cons<_Tp>(std::move(__tuple), _Indexes());
1067 }
1068
1069 template<class _T1, class _T2>
1070 template<typename _Tp, typename... _Args, std::size_t... _Indexes>
1071 inline _Tp
1072 pair<_T1, _T2>::__do_cons(tuple<_Args...>&& __tuple,
1073 const _Index_tuple<_Indexes...>&)
1074 { return _Tp(std::forward<_Args>(get<_Indexes>(__tuple))...); }
1075
1076 _GLIBCXX_END_NAMESPACE_VERSION
1077 } // namespace
1078
1079 #endif // __GXX_EXPERIMENTAL_CXX0X__
1080
1081 #endif // _GLIBCXX_TUPLE