1// <tuple> -*- C++ -*- 2 3// Copyright (C) 2007, 2008, 2009, 2010 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 40namespace std 41{ 42 // Adds a const reference to a non-reference type. 43 template<typename _Tp> 44 struct __add_c_ref 45 { typedef const _Tp& type; }; 46 47 template<typename _Tp> 48 struct __add_c_ref<_Tp&> 49 { typedef _Tp& type; }; 50 51 // Adds a reference to a non-reference type. 52 template<typename _Tp> 53 struct __add_ref 54 { typedef _Tp& type; }; 55 56 template<typename _Tp> 57 struct __add_ref<_Tp&> 58 { typedef _Tp& type; }; 59 60 template<std::size_t _Idx, typename _Head, bool _IsEmpty> 61 struct _Head_base; 62 63 template<std::size_t _Idx, typename _Head> 64 struct _Head_base<_Idx, _Head, true> 65 : public _Head 66 { 67 _Head_base() 68 : _Head() { } 69 70 _Head_base(const _Head& __h) 71 : _Head(__h) { } 72 73 template<typename _UHead> 74 _Head_base(_UHead&& __h) 75 : _Head(std::forward<_UHead>(__h)) { } 76 77 _Head& _M_head() { return *this; } 78 const _Head& _M_head() const { return *this; } 79 80 void _M_swap_impl(_Head&) { /* no-op */ } 81 }; 82 83 template<std::size_t _Idx, typename _Head> 84 struct _Head_base<_Idx, _Head, false> 85 { 86 _Head_base() 87 : _M_head_impl() { } 88 89 _Head_base(const _Head& __h) 90 : _M_head_impl(__h) { } 91 92 template<typename _UHead> 93 _Head_base(_UHead&& __h) 94 : _M_head_impl(std::forward<_UHead>(__h)) { } 95 96 _Head& _M_head() { return _M_head_impl; } 97 const _Head& _M_head() const { return _M_head_impl; } 98 99 void 100 _M_swap_impl(_Head& __h) 101 { 102 using std::swap; 103 swap(__h, _M_head_impl); 104 } 105 106 _Head _M_head_impl; 107 }; 108 109 /** 110 * Contains the actual implementation of the @c tuple template, stored 111 * as a recursive inheritance hierarchy from the first element (most 112 * derived class) to the last (least derived class). The @c Idx 113 * parameter gives the 0-based index of the element stored at this 114 * point in the hierarchy; we use it to implement a constant-time 115 * get() operation. 116 */ 117 template<std::size_t _Idx, typename... _Elements> 118 struct _Tuple_impl; 119 120 /** 121 * Zero-element tuple implementation. This is the basis case for the 122 * inheritance recursion. 123 */ 124 template<std::size_t _Idx> 125 struct _Tuple_impl<_Idx> 126 { 127 protected: 128 void _M_swap_impl(_Tuple_impl&) { /* no-op */ } 129 }; 130 131 /** 132 * Recursive tuple implementation. Here we store the @c Head element 133 * and derive from a @c Tuple_impl containing the remaining elements 134 * (which contains the @c Tail). 135 */ 136 template<std::size_t _Idx, typename _Head, typename... _Tail> 137 struct _Tuple_impl<_Idx, _Head, _Tail...> 138 : public _Tuple_impl<_Idx + 1, _Tail...>, 139 private _Head_base<_Idx, _Head, std::is_empty<_Head>::value> 140 { 141 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; 142 typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base; 143 144 _Head& _M_head() { return _Base::_M_head(); } 145 const _Head& _M_head() const { return _Base::_M_head(); } 146 147 _Inherited& _M_tail() { return *this; } 148 const _Inherited& _M_tail() const { return *this; } 149 150 _Tuple_impl() 151 : _Inherited(), _Base() { } 152 153 explicit 154 _Tuple_impl(const _Head& __head, const _Tail&... __tail) 155 : _Inherited(__tail...), _Base(__head) { } 156 157 template<typename _UHead, typename... _UTail> 158 explicit 159 _Tuple_impl(_UHead&& __head, _UTail&&... __tail) 160 : _Inherited(std::forward<_UTail>(__tail)...), 161 _Base(std::forward<_UHead>(__head)) { } 162 163 _Tuple_impl(const _Tuple_impl& __in) 164 : _Inherited(__in._M_tail()), _Base(__in._M_head()) { } 165 166 _Tuple_impl(_Tuple_impl&& __in) 167 : _Inherited(std::move(__in._M_tail())), 168 _Base(std::forward<_Head>(__in._M_head())) { } 169 170 template<typename... _UElements> 171 _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) 172 : _Inherited(__in._M_tail()), _Base(__in._M_head()) { } 173 174 template<typename... _UElements> 175 _Tuple_impl(_Tuple_impl<_Idx, _UElements...>&& __in) 176 : _Inherited(std::move(__in._M_tail())), 177 _Base(std::move(__in._M_head())) { } 178 179 _Tuple_impl& 180 operator=(const _Tuple_impl& __in) 181 { 182 _M_head() = __in._M_head(); 183 _M_tail() = __in._M_tail(); 184 return *this; 185 } 186 187 _Tuple_impl& 188 operator=(_Tuple_impl&& __in) 189 { 190 _M_head() = std::move(__in._M_head()); 191 _M_tail() = std::move(__in._M_tail()); 192 return *this; 193 } 194 195 template<typename... _UElements> 196 _Tuple_impl& 197 operator=(const _Tuple_impl<_Idx, _UElements...>& __in) 198 { 199 _M_head() = __in._M_head(); 200 _M_tail() = __in._M_tail(); 201 return *this; 202 } 203 204 template<typename... _UElements> 205 _Tuple_impl& 206 operator=(_Tuple_impl<_Idx, _UElements...>&& __in) 207 { 208 _M_head() = std::move(__in._M_head()); 209 _M_tail() = std::move(__in._M_tail()); 210 return *this; 211 } 212 213 protected: 214 void 215 _M_swap_impl(_Tuple_impl& __in) 216 { 217 _Base::_M_swap_impl(__in._M_head()); 218 _Inherited::_M_swap_impl(__in._M_tail()); 219 } 220 }; 221 222 /// tuple 223 template<typename... _Elements> 224 class tuple : public _Tuple_impl<0, _Elements...> 225 { 226 typedef _Tuple_impl<0, _Elements...> _Inherited; 227 228 public: 229 tuple() 230 : _Inherited() { } 231 232 explicit 233 tuple(const _Elements&... __elements) 234 : _Inherited(__elements...) { } 235 236 template<typename... _UElements> 237 explicit 238 tuple(_UElements&&... __elements) 239 : _Inherited(std::forward<_UElements>(__elements)...) { } 240 241 tuple(const tuple& __in) 242 : _Inherited(static_cast<const _Inherited&>(__in)) { } 243 244 tuple(tuple&& __in) 245 : _Inherited(static_cast<_Inherited&&>(__in)) { } 246 247 template<typename... _UElements> 248 tuple(const tuple<_UElements...>& __in) 249 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) 250 { } 251 252 template<typename... _UElements> 253 tuple(tuple<_UElements...>&& __in) 254 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } 255 256 // XXX http://gcc.gnu.org/ml/libstdc++/2008-02/msg00047.html 257 template<typename... _UElements> 258 tuple(tuple<_UElements...>& __in) 259 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) 260 { } 261 262 tuple& 263 operator=(const tuple& __in) 264 { 265 static_cast<_Inherited&>(*this) = __in; 266 return *this; 267 } 268 269 tuple& 270 operator=(tuple&& __in) 271 { 272 static_cast<_Inherited&>(*this) = std::move(__in); 273 return *this; 274 } 275 276 template<typename... _UElements> 277 tuple& 278 operator=(const tuple<_UElements...>& __in) 279 { 280 static_cast<_Inherited&>(*this) = __in; 281 return *this; 282 } 283 284 template<typename... _UElements> 285 tuple& 286 operator=(tuple<_UElements...>&& __in) 287 { 288 static_cast<_Inherited&>(*this) = std::move(__in); 289 return *this; 290 } 291 292 void 293 swap(tuple& __in) 294 { _Inherited::_M_swap_impl(__in); } 295 }; 296 297 298 template<> 299 class tuple<> 300 { 301 public: 302 void swap(tuple&) { /* no-op */ } 303 }; 304 305 /// tuple (2-element), with construction and assignment from a pair. 306 template<typename _T1, typename _T2> 307 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2> 308 { 309 typedef _Tuple_impl<0, _T1, _T2> _Inherited; 310 311 public: 312 tuple() 313 : _Inherited() { } 314 315 explicit 316 tuple(const _T1& __a1, const _T2& __a2) 317 : _Inherited(__a1, __a2) { } 318 319 template<typename _U1, typename _U2> 320 explicit 321 tuple(_U1&& __a1, _U2&& __a2) 322 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } 323 324 tuple(const tuple& __in) 325 : _Inherited(static_cast<const _Inherited&>(__in)) { } 326 327 tuple(tuple&& __in) 328 : _Inherited(static_cast<_Inherited&&>(__in)) { } 329 330 template<typename _U1, typename _U2> 331 tuple(const tuple<_U1, _U2>& __in) 332 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { } 333 334 template<typename _U1, typename _U2> 335 tuple(tuple<_U1, _U2>&& __in) 336 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } 337 338 template<typename _U1, typename _U2> 339 tuple(const pair<_U1, _U2>& __in) 340 : _Inherited(__in.first, __in.second) { } 341 342 template<typename _U1, typename _U2> 343 tuple(pair<_U1, _U2>&& __in) 344 : _Inherited(std::forward<_U1>(__in.first), 345 std::forward<_U2>(__in.second)) { } 346 347 tuple& 348 operator=(const tuple& __in) 349 { 350 static_cast<_Inherited&>(*this) = __in; 351 return *this; 352 } 353 354 tuple& 355 operator=(tuple&& __in) 356 { 357 static_cast<_Inherited&>(*this) = std::move(__in); 358 return *this; 359 } 360 361 template<typename _U1, typename _U2> 362 tuple& 363 operator=(const tuple<_U1, _U2>& __in) 364 { 365 static_cast<_Inherited&>(*this) = __in; 366 return *this; 367 } 368 369 template<typename _U1, typename _U2> 370 tuple& 371 operator=(tuple<_U1, _U2>&& __in) 372 { 373 static_cast<_Inherited&>(*this) = std::move(__in); 374 return *this; 375 } 376 377 template<typename _U1, typename _U2> 378 tuple& 379 operator=(const pair<_U1, _U2>& __in) 380 { 381 this->_M_head() = __in.first; 382 this->_M_tail()._M_head() = __in.second; 383 return *this; 384 } 385 386 template<typename _U1, typename _U2> 387 tuple& 388 operator=(pair<_U1, _U2>&& __in) 389 { 390 this->_M_head() = std::move(__in.first); 391 this->_M_tail()._M_head() = std::move(__in.second); 392 return *this; 393 } 394 395 void 396 swap(tuple& __in) 397 { 398 using std::swap; 399 swap(this->_M_head(), __in._M_head()); 400 swap(this->_M_tail()._M_head(), __in._M_tail()._M_head()); 401 } 402 }; 403 404 405 /// Gives the type of the ith element of a given tuple type. 406 template<std::size_t __i, typename _Tp> 407 struct tuple_element; 408 409 /** 410 * Recursive case for tuple_element: strip off the first element in 411 * the tuple and retrieve the (i-1)th element of the remaining tuple. 412 */ 413 template<std::size_t __i, typename _Head, typename... _Tail> 414 struct tuple_element<__i, tuple<_Head, _Tail...> > 415 : tuple_element<__i - 1, tuple<_Tail...> > { }; 416 417 /** 418 * Basis case for tuple_element: The first element is the one we're seeking. 419 */ 420 template<typename _Head, typename... _Tail> 421 struct tuple_element<0, tuple<_Head, _Tail...> > 422 { 423 typedef _Head type; 424 }; 425 426 /// Finds the size of a given tuple type. 427 template<typename _Tp> 428 struct tuple_size; 429 430 /// class tuple_size 431 template<typename... _Elements> 432 struct tuple_size<tuple<_Elements...> > 433 { 434 static const std::size_t value = sizeof...(_Elements); 435 }; 436 437 template<typename... _Elements> 438 const std::size_t tuple_size<tuple<_Elements...> >::value; 439 440 template<std::size_t __i, typename _Head, typename... _Tail> 441 inline typename __add_ref<_Head>::type 442 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) 443 { return __t._M_head(); } 444 445 template<std::size_t __i, typename _Head, typename... _Tail> 446 inline typename __add_c_ref<_Head>::type 447 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) 448 { return __t._M_head(); } 449 450 // Return a reference (const reference) to the ith element of a tuple. 451 // Any const or non-const ref elements are returned with their original type. 452 template<std::size_t __i, typename... _Elements> 453 inline typename __add_ref< 454 typename tuple_element<__i, tuple<_Elements...> >::type 455 >::type 456 get(tuple<_Elements...>& __t) 457 { return __get_helper<__i>(__t); } 458 459 template<std::size_t __i, typename... _Elements> 460 inline typename __add_c_ref< 461 typename tuple_element<__i, tuple<_Elements...> >::type 462 >::type 463 get(const tuple<_Elements...>& __t) 464 { return __get_helper<__i>(__t); } 465 466 // This class helps construct the various comparison operations on tuples 467 template<std::size_t __check_equal_size, std::size_t __i, std::size_t __j, 468 typename _Tp, typename _Up> 469 struct __tuple_compare; 470 471 template<std::size_t __i, std::size_t __j, typename _Tp, typename _Up> 472 struct __tuple_compare<0, __i, __j, _Tp, _Up> 473 { 474 static bool __eq(const _Tp& __t, const _Up& __u) 475 { 476 return (get<__i>(__t) == get<__i>(__u) && 477 __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__eq(__t, __u)); 478 } 479 480 static bool __less(const _Tp& __t, const _Up& __u) 481 { 482 return ((get<__i>(__t) < get<__i>(__u)) 483 || !(get<__i>(__u) < get<__i>(__t)) && 484 __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__less(__t, __u)); 485 } 486 }; 487 488 template<std::size_t __i, typename _Tp, typename _Up> 489 struct __tuple_compare<0, __i, __i, _Tp, _Up> 490 { 491 static bool __eq(const _Tp&, const _Up&) 492 { return true; } 493 494 static bool __less(const _Tp&, const _Up&) 495 { return false; } 496 }; 497 498 template<typename... _TElements, typename... _UElements> 499 bool 500 operator==(const tuple<_TElements...>& __t, 501 const tuple<_UElements...>& __u) 502 { 503 typedef tuple<_TElements...> _Tp; 504 typedef tuple<_UElements...> _Up; 505 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value, 506 0, tuple_size<_Tp>::value, _Tp, _Up>::__eq(__t, __u)); 507 } 508 509 template<typename... _TElements, typename... _UElements> 510 bool 511 operator<(const tuple<_TElements...>& __t, 512 const tuple<_UElements...>& __u) 513 { 514 typedef tuple<_TElements...> _Tp; 515 typedef tuple<_UElements...> _Up; 516 return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value, 517 0, tuple_size<_Tp>::value, _Tp, _Up>::__less(__t, __u)); 518 } 519 520 template<typename... _TElements, typename... _UElements> 521 inline bool 522 operator!=(const tuple<_TElements...>& __t, 523 const tuple<_UElements...>& __u) 524 { return !(__t == __u); } 525 526 template<typename... _TElements, typename... _UElements> 527 inline bool 528 operator>(const tuple<_TElements...>& __t, 529 const tuple<_UElements...>& __u) 530 { return __u < __t; } 531 532 template<typename... _TElements, typename... _UElements> 533 inline bool 534 operator<=(const tuple<_TElements...>& __t, 535 const tuple<_UElements...>& __u) 536 { return !(__u < __t); } 537 538 template<typename... _TElements, typename... _UElements> 539 inline bool 540 operator>=(const tuple<_TElements...>& __t, 541 const tuple<_UElements...>& __u) 542 { return !(__t < __u); } 543 544 // NB: DR 705. 545 template<typename... _Elements> 546 inline tuple<typename __decay_and_strip<_Elements>::__type...> 547 make_tuple(_Elements&&... __args) 548 { 549 typedef tuple<typename __decay_and_strip<_Elements>::__type...> 550 __result_type; 551 return __result_type(std::forward<_Elements>(__args)...); 552 } 553 554 template<std::size_t...> struct __index_holder { }; 555 556 template<std::size_t __i, typename _IdxHolder, typename... _Elements> 557 struct __index_holder_impl; 558 559 template<std::size_t __i, std::size_t... _Indexes, typename _IdxHolder, 560 typename... _Elements> 561 struct __index_holder_impl<__i, __index_holder<_Indexes...>, 562 _IdxHolder, _Elements...> 563 { 564 typedef typename __index_holder_impl<__i + 1, 565 __index_holder<_Indexes..., __i>, 566 _Elements...>::type type; 567 }; 568 569 template<std::size_t __i, std::size_t... _Indexes> 570 struct __index_holder_impl<__i, __index_holder<_Indexes...> > 571 { typedef __index_holder<_Indexes...> type; }; 572 573 template<typename... _Elements> 574 struct __make_index_holder 575 : __index_holder_impl<0, __index_holder<>, _Elements...> { }; 576 577 template<typename... _TElements, std::size_t... _TIdx, 578 typename... _UElements, std::size_t... _UIdx> 579 inline tuple<_TElements..., _UElements...> 580 __tuple_cat_helper(const tuple<_TElements...>& __t, 581 const __index_holder<_TIdx...>&, 582 const tuple<_UElements...>& __u, 583 const __index_holder<_UIdx...>&) 584 { return tuple<_TElements..., _UElements...>(get<_TIdx>(__t)..., 585 get<_UIdx>(__u)...); } 586 587 template<typename... _TElements, std::size_t... _TIdx, 588 typename... _UElements, std::size_t... _UIdx> 589 inline tuple<_TElements..., _UElements...> 590 __tuple_cat_helper(tuple<_TElements...>&& __t, 591 const __index_holder<_TIdx...>&, 592 const tuple<_UElements...>& __u, 593 const __index_holder<_UIdx...>&) 594 { return tuple<_TElements..., _UElements...> 595 (std::move(get<_TIdx>(__t))..., get<_UIdx>(__u)...); } 596 597 template<typename... _TElements, std::size_t... _TIdx, 598 typename... _UElements, std::size_t... _UIdx> 599 inline tuple<_TElements..., _UElements...> 600 __tuple_cat_helper(const tuple<_TElements...>& __t, 601 const __index_holder<_TIdx...>&, 602 tuple<_UElements...>&& __u, 603 const __index_holder<_UIdx...>&) 604 { return tuple<_TElements..., _UElements...> 605 (get<_TIdx>(__t)..., std::move(get<_UIdx>(__u))...); } 606 607 template<typename... _TElements, std::size_t... _TIdx, 608 typename... _UElements, std::size_t... _UIdx> 609 inline tuple<_TElements..., _UElements...> 610 __tuple_cat_helper(tuple<_TElements...>&& __t, 611 const __index_holder<_TIdx...>&, 612 tuple<_UElements...>&& __u, 613 const __index_holder<_UIdx...>&) 614 { return tuple<_TElements..., _UElements...> 615 (std::move(get<_TIdx>(__t))..., std::move(get<_UIdx>(__u))...); } 616 617 template<typename... _TElements, typename... _UElements> 618 inline tuple<_TElements..., _UElements...> 619 tuple_cat(const tuple<_TElements...>& __t, const tuple<_UElements...>& __u) 620 { 621 return __tuple_cat_helper(__t, typename 622 __make_index_holder<_TElements...>::type(), 623 __u, typename 624 __make_index_holder<_UElements...>::type()); 625 } 626 627 template<typename... _TElements, typename... _UElements> 628 inline tuple<_TElements..., _UElements...> 629 tuple_cat(tuple<_TElements...>&& __t, const tuple<_UElements...>& __u) 630 { 631 return __tuple_cat_helper(std::move(__t), typename 632 __make_index_holder<_TElements...>::type(), 633 __u, typename 634 __make_index_holder<_UElements...>::type()); 635 } 636 637 template<typename... _TElements, typename... _UElements> 638 inline tuple<_TElements..., _UElements...> 639 tuple_cat(const tuple<_TElements...>& __t, tuple<_UElements...>&& __u) 640 { 641 return __tuple_cat_helper(__t, typename 642 __make_index_holder<_TElements...>::type(), 643 std::move(__u), typename 644 __make_index_holder<_UElements...>::type()); 645 } 646 647 template<typename... _TElements, typename... _UElements> 648 inline tuple<_TElements..., _UElements...> 649 tuple_cat(tuple<_TElements...>&& __t, tuple<_UElements...>&& __u) 650 { 651 return __tuple_cat_helper(std::move(__t), typename 652 __make_index_holder<_TElements...>::type(), 653 std::move(__u), typename 654 __make_index_holder<_UElements...>::type()); 655 } 656 657 template<typename... _Elements> 658 inline tuple<_Elements&...> 659 tie(_Elements&... __args) 660 { return tuple<_Elements&...>(__args...); } 661 662 template<typename... _Elements> 663 inline void 664 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y) 665 { __x.swap(__y); } 666 667 // A class (and instance) which can be used in 'tie' when an element 668 // of a tuple is not required 669 struct _Swallow_assign 670 { 671 template<class _Tp> 672 _Swallow_assign& 673 operator=(const _Tp&) 674 { return *this; } 675 }; 676 677 // TODO: Put this in some kind of shared file. 678 namespace 679 { 680 _Swallow_assign ignore; 681 }; // anonymous namespace 682} 683 684#endif // __GXX_EXPERIMENTAL_CXX0X__ 685 686#endif // _GLIBCXX_TUPLE 687