libstdc++
|
00001 // <tuple> -*- C++ -*- 00002 00003 // Copyright (C) 2007-2018 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file include/tuple 00026 * This is a Standard C++ Library header. 00027 */ 00028 00029 #ifndef _GLIBCXX_TUPLE 00030 #define _GLIBCXX_TUPLE 1 00031 00032 #pragma GCC system_header 00033 00034 #if __cplusplus < 201103L 00035 # include <bits/c++0x_warning.h> 00036 #else 00037 00038 #include <utility> 00039 #include <array> 00040 #include <bits/uses_allocator.h> 00041 #include <bits/invoke.h> 00042 00043 namespace std _GLIBCXX_VISIBILITY(default) 00044 { 00045 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00046 00047 /** 00048 * @addtogroup utilities 00049 * @{ 00050 */ 00051 00052 template<typename... _Elements> 00053 class tuple; 00054 00055 template<typename _Tp> 00056 struct __is_empty_non_tuple : is_empty<_Tp> { }; 00057 00058 // Using EBO for elements that are tuples causes ambiguous base errors. 00059 template<typename _El0, typename... _El> 00060 struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { }; 00061 00062 // Use the Empty Base-class Optimization for empty, non-final types. 00063 template<typename _Tp> 00064 using __empty_not_final 00065 = typename conditional<__is_final(_Tp), false_type, 00066 __is_empty_non_tuple<_Tp>>::type; 00067 00068 template<std::size_t _Idx, typename _Head, 00069 bool = __empty_not_final<_Head>::value> 00070 struct _Head_base; 00071 00072 template<std::size_t _Idx, typename _Head> 00073 struct _Head_base<_Idx, _Head, true> 00074 : public _Head 00075 { 00076 constexpr _Head_base() 00077 : _Head() { } 00078 00079 constexpr _Head_base(const _Head& __h) 00080 : _Head(__h) { } 00081 00082 constexpr _Head_base(const _Head_base&) = default; 00083 constexpr _Head_base(_Head_base&&) = default; 00084 00085 template<typename _UHead> 00086 constexpr _Head_base(_UHead&& __h) 00087 : _Head(std::forward<_UHead>(__h)) { } 00088 00089 _Head_base(allocator_arg_t, __uses_alloc0) 00090 : _Head() { } 00091 00092 template<typename _Alloc> 00093 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) 00094 : _Head(allocator_arg, *__a._M_a) { } 00095 00096 template<typename _Alloc> 00097 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) 00098 : _Head(*__a._M_a) { } 00099 00100 template<typename _UHead> 00101 _Head_base(__uses_alloc0, _UHead&& __uhead) 00102 : _Head(std::forward<_UHead>(__uhead)) { } 00103 00104 template<typename _Alloc, typename _UHead> 00105 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) 00106 : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { } 00107 00108 template<typename _Alloc, typename _UHead> 00109 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) 00110 : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { } 00111 00112 static constexpr _Head& 00113 _M_head(_Head_base& __b) noexcept { return __b; } 00114 00115 static constexpr const _Head& 00116 _M_head(const _Head_base& __b) noexcept { return __b; } 00117 }; 00118 00119 template<std::size_t _Idx, typename _Head> 00120 struct _Head_base<_Idx, _Head, false> 00121 { 00122 constexpr _Head_base() 00123 : _M_head_impl() { } 00124 00125 constexpr _Head_base(const _Head& __h) 00126 : _M_head_impl(__h) { } 00127 00128 constexpr _Head_base(const _Head_base&) = default; 00129 constexpr _Head_base(_Head_base&&) = default; 00130 00131 template<typename _UHead> 00132 constexpr _Head_base(_UHead&& __h) 00133 : _M_head_impl(std::forward<_UHead>(__h)) { } 00134 00135 _Head_base(allocator_arg_t, __uses_alloc0) 00136 : _M_head_impl() { } 00137 00138 template<typename _Alloc> 00139 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) 00140 : _M_head_impl(allocator_arg, *__a._M_a) { } 00141 00142 template<typename _Alloc> 00143 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) 00144 : _M_head_impl(*__a._M_a) { } 00145 00146 template<typename _UHead> 00147 _Head_base(__uses_alloc0, _UHead&& __uhead) 00148 : _M_head_impl(std::forward<_UHead>(__uhead)) { } 00149 00150 template<typename _Alloc, typename _UHead> 00151 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) 00152 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) 00153 { } 00154 00155 template<typename _Alloc, typename _UHead> 00156 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) 00157 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } 00158 00159 static constexpr _Head& 00160 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; } 00161 00162 static constexpr const _Head& 00163 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } 00164 00165 _Head _M_head_impl; 00166 }; 00167 00168 /** 00169 * Contains the actual implementation of the @c tuple template, stored 00170 * as a recursive inheritance hierarchy from the first element (most 00171 * derived class) to the last (least derived class). The @c Idx 00172 * parameter gives the 0-based index of the element stored at this 00173 * point in the hierarchy; we use it to implement a constant-time 00174 * get() operation. 00175 */ 00176 template<std::size_t _Idx, typename... _Elements> 00177 struct _Tuple_impl; 00178 00179 /** 00180 * Recursive tuple implementation. Here we store the @c Head element 00181 * and derive from a @c Tuple_impl containing the remaining elements 00182 * (which contains the @c Tail). 00183 */ 00184 template<std::size_t _Idx, typename _Head, typename... _Tail> 00185 struct _Tuple_impl<_Idx, _Head, _Tail...> 00186 : public _Tuple_impl<_Idx + 1, _Tail...>, 00187 private _Head_base<_Idx, _Head> 00188 { 00189 template<std::size_t, typename...> friend class _Tuple_impl; 00190 00191 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; 00192 typedef _Head_base<_Idx, _Head> _Base; 00193 00194 static constexpr _Head& 00195 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } 00196 00197 static constexpr const _Head& 00198 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } 00199 00200 static constexpr _Inherited& 00201 _M_tail(_Tuple_impl& __t) noexcept { return __t; } 00202 00203 static constexpr const _Inherited& 00204 _M_tail(const _Tuple_impl& __t) noexcept { return __t; } 00205 00206 constexpr _Tuple_impl() 00207 : _Inherited(), _Base() { } 00208 00209 explicit 00210 constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail) 00211 : _Inherited(__tail...), _Base(__head) { } 00212 00213 template<typename _UHead, typename... _UTail, typename = typename 00214 enable_if<sizeof...(_Tail) == sizeof...(_UTail)>::type> 00215 explicit 00216 constexpr _Tuple_impl(_UHead&& __head, _UTail&&... __tail) 00217 : _Inherited(std::forward<_UTail>(__tail)...), 00218 _Base(std::forward<_UHead>(__head)) { } 00219 00220 constexpr _Tuple_impl(const _Tuple_impl&) = default; 00221 00222 constexpr 00223 _Tuple_impl(_Tuple_impl&& __in) 00224 noexcept(__and_<is_nothrow_move_constructible<_Head>, 00225 is_nothrow_move_constructible<_Inherited>>::value) 00226 : _Inherited(std::move(_M_tail(__in))), 00227 _Base(std::forward<_Head>(_M_head(__in))) { } 00228 00229 template<typename... _UElements> 00230 constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) 00231 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), 00232 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } 00233 00234 template<typename _UHead, typename... _UTails> 00235 constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) 00236 : _Inherited(std::move 00237 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), 00238 _Base(std::forward<_UHead> 00239 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } 00240 00241 template<typename _Alloc> 00242 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) 00243 : _Inherited(__tag, __a), 00244 _Base(__tag, __use_alloc<_Head>(__a)) { } 00245 00246 template<typename _Alloc> 00247 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00248 const _Head& __head, const _Tail&... __tail) 00249 : _Inherited(__tag, __a, __tail...), 00250 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } 00251 00252 template<typename _Alloc, typename _UHead, typename... _UTail, 00253 typename = typename enable_if<sizeof...(_Tail) 00254 == sizeof...(_UTail)>::type> 00255 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00256 _UHead&& __head, _UTail&&... __tail) 00257 : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...), 00258 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), 00259 std::forward<_UHead>(__head)) { } 00260 00261 template<typename _Alloc> 00262 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00263 const _Tuple_impl& __in) 00264 : _Inherited(__tag, __a, _M_tail(__in)), 00265 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } 00266 00267 template<typename _Alloc> 00268 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00269 _Tuple_impl&& __in) 00270 : _Inherited(__tag, __a, std::move(_M_tail(__in))), 00271 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), 00272 std::forward<_Head>(_M_head(__in))) { } 00273 00274 template<typename _Alloc, typename... _UElements> 00275 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00276 const _Tuple_impl<_Idx, _UElements...>& __in) 00277 : _Inherited(__tag, __a, 00278 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), 00279 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), 00280 _Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } 00281 00282 template<typename _Alloc, typename _UHead, typename... _UTails> 00283 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00284 _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) 00285 : _Inherited(__tag, __a, std::move 00286 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), 00287 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), 00288 std::forward<_UHead> 00289 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } 00290 00291 _Tuple_impl& 00292 operator=(const _Tuple_impl& __in) 00293 { 00294 _M_head(*this) = _M_head(__in); 00295 _M_tail(*this) = _M_tail(__in); 00296 return *this; 00297 } 00298 00299 _Tuple_impl& 00300 operator=(_Tuple_impl&& __in) 00301 noexcept(__and_<is_nothrow_move_assignable<_Head>, 00302 is_nothrow_move_assignable<_Inherited>>::value) 00303 { 00304 _M_head(*this) = std::forward<_Head>(_M_head(__in)); 00305 _M_tail(*this) = std::move(_M_tail(__in)); 00306 return *this; 00307 } 00308 00309 template<typename... _UElements> 00310 _Tuple_impl& 00311 operator=(const _Tuple_impl<_Idx, _UElements...>& __in) 00312 { 00313 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in); 00314 _M_tail(*this) = _Tuple_impl<_Idx, _UElements...>::_M_tail(__in); 00315 return *this; 00316 } 00317 00318 template<typename _UHead, typename... _UTails> 00319 _Tuple_impl& 00320 operator=(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) 00321 { 00322 _M_head(*this) = std::forward<_UHead> 00323 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)); 00324 _M_tail(*this) = std::move 00325 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)); 00326 return *this; 00327 } 00328 00329 protected: 00330 void 00331 _M_swap(_Tuple_impl& __in) 00332 noexcept(__is_nothrow_swappable<_Head>::value 00333 && noexcept(_M_tail(__in)._M_swap(_M_tail(__in)))) 00334 { 00335 using std::swap; 00336 swap(_M_head(*this), _M_head(__in)); 00337 _Inherited::_M_swap(_M_tail(__in)); 00338 } 00339 }; 00340 00341 // Basis case of inheritance recursion. 00342 template<std::size_t _Idx, typename _Head> 00343 struct _Tuple_impl<_Idx, _Head> 00344 : private _Head_base<_Idx, _Head> 00345 { 00346 template<std::size_t, typename...> friend class _Tuple_impl; 00347 00348 typedef _Head_base<_Idx, _Head> _Base; 00349 00350 static constexpr _Head& 00351 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } 00352 00353 static constexpr const _Head& 00354 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } 00355 00356 constexpr _Tuple_impl() 00357 : _Base() { } 00358 00359 explicit 00360 constexpr _Tuple_impl(const _Head& __head) 00361 : _Base(__head) { } 00362 00363 template<typename _UHead> 00364 explicit 00365 constexpr _Tuple_impl(_UHead&& __head) 00366 : _Base(std::forward<_UHead>(__head)) { } 00367 00368 constexpr _Tuple_impl(const _Tuple_impl&) = default; 00369 00370 constexpr 00371 _Tuple_impl(_Tuple_impl&& __in) 00372 noexcept(is_nothrow_move_constructible<_Head>::value) 00373 : _Base(std::forward<_Head>(_M_head(__in))) { } 00374 00375 template<typename _UHead> 00376 constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in) 00377 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } 00378 00379 template<typename _UHead> 00380 constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in) 00381 : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) 00382 { } 00383 00384 template<typename _Alloc> 00385 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) 00386 : _Base(__tag, __use_alloc<_Head>(__a)) { } 00387 00388 template<typename _Alloc> 00389 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00390 const _Head& __head) 00391 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } 00392 00393 template<typename _Alloc, typename _UHead> 00394 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00395 _UHead&& __head) 00396 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), 00397 std::forward<_UHead>(__head)) { } 00398 00399 template<typename _Alloc> 00400 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00401 const _Tuple_impl& __in) 00402 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } 00403 00404 template<typename _Alloc> 00405 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00406 _Tuple_impl&& __in) 00407 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), 00408 std::forward<_Head>(_M_head(__in))) { } 00409 00410 template<typename _Alloc, typename _UHead> 00411 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00412 const _Tuple_impl<_Idx, _UHead>& __in) 00413 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), 00414 _Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } 00415 00416 template<typename _Alloc, typename _UHead> 00417 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 00418 _Tuple_impl<_Idx, _UHead>&& __in) 00419 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), 00420 std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) 00421 { } 00422 00423 _Tuple_impl& 00424 operator=(const _Tuple_impl& __in) 00425 { 00426 _M_head(*this) = _M_head(__in); 00427 return *this; 00428 } 00429 00430 _Tuple_impl& 00431 operator=(_Tuple_impl&& __in) 00432 noexcept(is_nothrow_move_assignable<_Head>::value) 00433 { 00434 _M_head(*this) = std::forward<_Head>(_M_head(__in)); 00435 return *this; 00436 } 00437 00438 template<typename _UHead> 00439 _Tuple_impl& 00440 operator=(const _Tuple_impl<_Idx, _UHead>& __in) 00441 { 00442 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in); 00443 return *this; 00444 } 00445 00446 template<typename _UHead> 00447 _Tuple_impl& 00448 operator=(_Tuple_impl<_Idx, _UHead>&& __in) 00449 { 00450 _M_head(*this) 00451 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)); 00452 return *this; 00453 } 00454 00455 protected: 00456 void 00457 _M_swap(_Tuple_impl& __in) 00458 noexcept(__is_nothrow_swappable<_Head>::value) 00459 { 00460 using std::swap; 00461 swap(_M_head(*this), _M_head(__in)); 00462 } 00463 }; 00464 00465 // Concept utility functions, reused in conditionally-explicit 00466 // constructors. 00467 template<bool, typename... _Elements> 00468 struct _TC 00469 { 00470 template<typename... _UElements> 00471 static constexpr bool _ConstructibleTuple() 00472 { 00473 return __and_<is_constructible<_Elements, const _UElements&>...>::value; 00474 } 00475 00476 template<typename... _UElements> 00477 static constexpr bool _ImplicitlyConvertibleTuple() 00478 { 00479 return __and_<is_convertible<const _UElements&, _Elements>...>::value; 00480 } 00481 00482 template<typename... _UElements> 00483 static constexpr bool _MoveConstructibleTuple() 00484 { 00485 return __and_<is_constructible<_Elements, _UElements&&>...>::value; 00486 } 00487 00488 template<typename... _UElements> 00489 static constexpr bool _ImplicitlyMoveConvertibleTuple() 00490 { 00491 return __and_<is_convertible<_UElements&&, _Elements>...>::value; 00492 } 00493 00494 template<typename _SrcTuple> 00495 static constexpr bool _NonNestedTuple() 00496 { 00497 return __and_<__not_<is_same<tuple<_Elements...>, 00498 typename remove_cv< 00499 typename remove_reference<_SrcTuple>::type 00500 >::type>>, 00501 __not_<is_convertible<_SrcTuple, _Elements...>>, 00502 __not_<is_constructible<_Elements..., _SrcTuple>> 00503 >::value; 00504 } 00505 template<typename... _UElements> 00506 static constexpr bool _NotSameTuple() 00507 { 00508 return __not_<is_same<tuple<_Elements...>, 00509 typename remove_const< 00510 typename remove_reference<_UElements...>::type 00511 >::type>>::value; 00512 } 00513 }; 00514 00515 template<typename... _Elements> 00516 struct _TC<false, _Elements...> 00517 { 00518 template<typename... _UElements> 00519 static constexpr bool _ConstructibleTuple() 00520 { 00521 return false; 00522 } 00523 00524 template<typename... _UElements> 00525 static constexpr bool _ImplicitlyConvertibleTuple() 00526 { 00527 return false; 00528 } 00529 00530 template<typename... _UElements> 00531 static constexpr bool _MoveConstructibleTuple() 00532 { 00533 return false; 00534 } 00535 00536 template<typename... _UElements> 00537 static constexpr bool _ImplicitlyMoveConvertibleTuple() 00538 { 00539 return false; 00540 } 00541 00542 template<typename... _UElements> 00543 static constexpr bool _NonNestedTuple() 00544 { 00545 return true; 00546 } 00547 template<typename... _UElements> 00548 static constexpr bool _NotSameTuple() 00549 { 00550 return true; 00551 } 00552 }; 00553 00554 /// Primary class template, tuple 00555 template<typename... _Elements> 00556 class tuple : public _Tuple_impl<0, _Elements...> 00557 { 00558 typedef _Tuple_impl<0, _Elements...> _Inherited; 00559 00560 // Used for constraining the default constructor so 00561 // that it becomes dependent on the constraints. 00562 template<typename _Dummy> 00563 struct _TC2 00564 { 00565 static constexpr bool _DefaultConstructibleTuple() 00566 { 00567 return __and_<is_default_constructible<_Elements>...>::value; 00568 } 00569 static constexpr bool _ImplicitlyDefaultConstructibleTuple() 00570 { 00571 return __and_<__is_implicitly_default_constructible<_Elements>...> 00572 ::value; 00573 } 00574 }; 00575 00576 public: 00577 template<typename _Dummy = void, 00578 typename enable_if<_TC2<_Dummy>:: 00579 _ImplicitlyDefaultConstructibleTuple(), 00580 bool>::type = true> 00581 constexpr tuple() 00582 : _Inherited() { } 00583 00584 template<typename _Dummy = void, 00585 typename enable_if<_TC2<_Dummy>:: 00586 _DefaultConstructibleTuple() 00587 && 00588 !_TC2<_Dummy>:: 00589 _ImplicitlyDefaultConstructibleTuple(), 00590 bool>::type = false> 00591 explicit constexpr tuple() 00592 : _Inherited() { } 00593 00594 // Shortcut for the cases where constructors taking _Elements... 00595 // need to be constrained. 00596 template<typename _Dummy> using _TCC = 00597 _TC<is_same<_Dummy, void>::value, 00598 _Elements...>; 00599 00600 template<typename _Dummy = void, 00601 typename enable_if< 00602 _TCC<_Dummy>::template 00603 _ConstructibleTuple<_Elements...>() 00604 && _TCC<_Dummy>::template 00605 _ImplicitlyConvertibleTuple<_Elements...>() 00606 && (sizeof...(_Elements) >= 1), 00607 bool>::type=true> 00608 constexpr tuple(const _Elements&... __elements) 00609 : _Inherited(__elements...) { } 00610 00611 template<typename _Dummy = void, 00612 typename enable_if< 00613 _TCC<_Dummy>::template 00614 _ConstructibleTuple<_Elements...>() 00615 && !_TCC<_Dummy>::template 00616 _ImplicitlyConvertibleTuple<_Elements...>() 00617 && (sizeof...(_Elements) >= 1), 00618 bool>::type=false> 00619 explicit constexpr tuple(const _Elements&... __elements) 00620 : _Inherited(__elements...) { } 00621 00622 // Shortcut for the cases where constructors taking _UElements... 00623 // need to be constrained. 00624 template<typename... _UElements> using _TMC = 00625 _TC<(sizeof...(_Elements) == sizeof...(_UElements)) 00626 && (_TC<(sizeof...(_UElements)==1), _Elements...>:: 00627 template _NotSameTuple<_UElements...>()), 00628 _Elements...>; 00629 00630 // Shortcut for the cases where constructors taking tuple<_UElements...> 00631 // need to be constrained. 00632 template<typename... _UElements> using _TMCT = 00633 _TC<(sizeof...(_Elements) == sizeof...(_UElements)) 00634 && !is_same<tuple<_Elements...>, 00635 tuple<_UElements...>>::value, 00636 _Elements...>; 00637 00638 template<typename... _UElements, typename 00639 enable_if< 00640 _TMC<_UElements...>::template 00641 _MoveConstructibleTuple<_UElements...>() 00642 && _TMC<_UElements...>::template 00643 _ImplicitlyMoveConvertibleTuple<_UElements...>() 00644 && (sizeof...(_Elements) >= 1), 00645 bool>::type=true> 00646 constexpr tuple(_UElements&&... __elements) 00647 : _Inherited(std::forward<_UElements>(__elements)...) { } 00648 00649 template<typename... _UElements, typename 00650 enable_if< 00651 _TMC<_UElements...>::template 00652 _MoveConstructibleTuple<_UElements...>() 00653 && !_TMC<_UElements...>::template 00654 _ImplicitlyMoveConvertibleTuple<_UElements...>() 00655 && (sizeof...(_Elements) >= 1), 00656 bool>::type=false> 00657 explicit constexpr tuple(_UElements&&... __elements) 00658 : _Inherited(std::forward<_UElements>(__elements)...) { } 00659 00660 constexpr tuple(const tuple&) = default; 00661 00662 constexpr tuple(tuple&&) = default; 00663 00664 // Shortcut for the cases where constructors taking tuples 00665 // must avoid creating temporaries. 00666 template<typename _Dummy> using _TNTC = 00667 _TC<is_same<_Dummy, void>::value && sizeof...(_Elements) == 1, 00668 _Elements...>; 00669 00670 template<typename... _UElements, typename _Dummy = void, typename 00671 enable_if<_TMCT<_UElements...>::template 00672 _ConstructibleTuple<_UElements...>() 00673 && _TMCT<_UElements...>::template 00674 _ImplicitlyConvertibleTuple<_UElements...>() 00675 && _TNTC<_Dummy>::template 00676 _NonNestedTuple<const tuple<_UElements...>&>(), 00677 bool>::type=true> 00678 constexpr tuple(const tuple<_UElements...>& __in) 00679 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) 00680 { } 00681 00682 template<typename... _UElements, typename _Dummy = void, typename 00683 enable_if<_TMCT<_UElements...>::template 00684 _ConstructibleTuple<_UElements...>() 00685 && !_TMCT<_UElements...>::template 00686 _ImplicitlyConvertibleTuple<_UElements...>() 00687 && _TNTC<_Dummy>::template 00688 _NonNestedTuple<const tuple<_UElements...>&>(), 00689 bool>::type=false> 00690 explicit constexpr tuple(const tuple<_UElements...>& __in) 00691 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) 00692 { } 00693 00694 template<typename... _UElements, typename _Dummy = void, typename 00695 enable_if<_TMCT<_UElements...>::template 00696 _MoveConstructibleTuple<_UElements...>() 00697 && _TMCT<_UElements...>::template 00698 _ImplicitlyMoveConvertibleTuple<_UElements...>() 00699 && _TNTC<_Dummy>::template 00700 _NonNestedTuple<tuple<_UElements...>&&>(), 00701 bool>::type=true> 00702 constexpr tuple(tuple<_UElements...>&& __in) 00703 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } 00704 00705 template<typename... _UElements, typename _Dummy = void, typename 00706 enable_if<_TMCT<_UElements...>::template 00707 _MoveConstructibleTuple<_UElements...>() 00708 && !_TMCT<_UElements...>::template 00709 _ImplicitlyMoveConvertibleTuple<_UElements...>() 00710 && _TNTC<_Dummy>::template 00711 _NonNestedTuple<tuple<_UElements...>&&>(), 00712 bool>::type=false> 00713 explicit constexpr tuple(tuple<_UElements...>&& __in) 00714 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } 00715 00716 // Allocator-extended constructors. 00717 00718 template<typename _Alloc> 00719 tuple(allocator_arg_t __tag, const _Alloc& __a) 00720 : _Inherited(__tag, __a) { } 00721 00722 template<typename _Alloc, typename _Dummy = void, 00723 typename enable_if< 00724 _TCC<_Dummy>::template 00725 _ConstructibleTuple<_Elements...>() 00726 && _TCC<_Dummy>::template 00727 _ImplicitlyConvertibleTuple<_Elements...>(), 00728 bool>::type=true> 00729 tuple(allocator_arg_t __tag, const _Alloc& __a, 00730 const _Elements&... __elements) 00731 : _Inherited(__tag, __a, __elements...) { } 00732 00733 template<typename _Alloc, typename _Dummy = void, 00734 typename enable_if< 00735 _TCC<_Dummy>::template 00736 _ConstructibleTuple<_Elements...>() 00737 && !_TCC<_Dummy>::template 00738 _ImplicitlyConvertibleTuple<_Elements...>(), 00739 bool>::type=false> 00740 explicit tuple(allocator_arg_t __tag, const _Alloc& __a, 00741 const _Elements&... __elements) 00742 : _Inherited(__tag, __a, __elements...) { } 00743 00744 template<typename _Alloc, typename... _UElements, typename 00745 enable_if<_TMC<_UElements...>::template 00746 _MoveConstructibleTuple<_UElements...>() 00747 && _TMC<_UElements...>::template 00748 _ImplicitlyMoveConvertibleTuple<_UElements...>(), 00749 bool>::type=true> 00750 tuple(allocator_arg_t __tag, const _Alloc& __a, 00751 _UElements&&... __elements) 00752 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) 00753 { } 00754 00755 template<typename _Alloc, typename... _UElements, typename 00756 enable_if<_TMC<_UElements...>::template 00757 _MoveConstructibleTuple<_UElements...>() 00758 && !_TMC<_UElements...>::template 00759 _ImplicitlyMoveConvertibleTuple<_UElements...>(), 00760 bool>::type=false> 00761 explicit tuple(allocator_arg_t __tag, const _Alloc& __a, 00762 _UElements&&... __elements) 00763 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) 00764 { } 00765 00766 template<typename _Alloc> 00767 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) 00768 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { } 00769 00770 template<typename _Alloc> 00771 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) 00772 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } 00773 00774 template<typename _Alloc, typename _Dummy = void, 00775 typename... _UElements, typename 00776 enable_if<_TMCT<_UElements...>::template 00777 _ConstructibleTuple<_UElements...>() 00778 && _TMCT<_UElements...>::template 00779 _ImplicitlyConvertibleTuple<_UElements...>() 00780 && _TNTC<_Dummy>::template 00781 _NonNestedTuple<tuple<_UElements...>&&>(), 00782 bool>::type=true> 00783 tuple(allocator_arg_t __tag, const _Alloc& __a, 00784 const tuple<_UElements...>& __in) 00785 : _Inherited(__tag, __a, 00786 static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) 00787 { } 00788 00789 template<typename _Alloc, typename _Dummy = void, 00790 typename... _UElements, typename 00791 enable_if<_TMCT<_UElements...>::template 00792 _ConstructibleTuple<_UElements...>() 00793 && !_TMCT<_UElements...>::template 00794 _ImplicitlyConvertibleTuple<_UElements...>() 00795 && _TNTC<_Dummy>::template 00796 _NonNestedTuple<tuple<_UElements...>&&>(), 00797 bool>::type=false> 00798 explicit tuple(allocator_arg_t __tag, const _Alloc& __a, 00799 const tuple<_UElements...>& __in) 00800 : _Inherited(__tag, __a, 00801 static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) 00802 { } 00803 00804 template<typename _Alloc, typename _Dummy = void, 00805 typename... _UElements, typename 00806 enable_if<_TMCT<_UElements...>::template 00807 _MoveConstructibleTuple<_UElements...>() 00808 && _TMCT<_UElements...>::template 00809 _ImplicitlyMoveConvertibleTuple<_UElements...>() 00810 && _TNTC<_Dummy>::template 00811 _NonNestedTuple<tuple<_UElements...>&&>(), 00812 bool>::type=true> 00813 tuple(allocator_arg_t __tag, const _Alloc& __a, 00814 tuple<_UElements...>&& __in) 00815 : _Inherited(__tag, __a, 00816 static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) 00817 { } 00818 00819 template<typename _Alloc, typename _Dummy = void, 00820 typename... _UElements, typename 00821 enable_if<_TMCT<_UElements...>::template 00822 _MoveConstructibleTuple<_UElements...>() 00823 && !_TMCT<_UElements...>::template 00824 _ImplicitlyMoveConvertibleTuple<_UElements...>() 00825 && _TNTC<_Dummy>::template 00826 _NonNestedTuple<tuple<_UElements...>&&>(), 00827 bool>::type=false> 00828 explicit tuple(allocator_arg_t __tag, const _Alloc& __a, 00829 tuple<_UElements...>&& __in) 00830 : _Inherited(__tag, __a, 00831 static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) 00832 { } 00833 00834 tuple& 00835 operator=(const tuple& __in) 00836 { 00837 static_cast<_Inherited&>(*this) = __in; 00838 return *this; 00839 } 00840 00841 tuple& 00842 operator=(tuple&& __in) 00843 noexcept(is_nothrow_move_assignable<_Inherited>::value) 00844 { 00845 static_cast<_Inherited&>(*this) = std::move(__in); 00846 return *this; 00847 } 00848 00849 template<typename... _UElements> 00850 typename 00851 enable_if<sizeof...(_UElements) 00852 == sizeof...(_Elements), tuple&>::type 00853 operator=(const tuple<_UElements...>& __in) 00854 { 00855 static_cast<_Inherited&>(*this) = __in; 00856 return *this; 00857 } 00858 00859 template<typename... _UElements> 00860 typename 00861 enable_if<sizeof...(_UElements) 00862 == sizeof...(_Elements), tuple&>::type 00863 operator=(tuple<_UElements...>&& __in) 00864 { 00865 static_cast<_Inherited&>(*this) = std::move(__in); 00866 return *this; 00867 } 00868 00869 void 00870 swap(tuple& __in) 00871 noexcept(noexcept(__in._M_swap(__in))) 00872 { _Inherited::_M_swap(__in); } 00873 }; 00874 00875 #if __cpp_deduction_guides >= 201606 00876 template<typename... _UTypes> 00877 tuple(_UTypes...) -> tuple<_UTypes...>; 00878 template<typename _T1, typename _T2> 00879 tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>; 00880 template<typename _Alloc, typename... _UTypes> 00881 tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>; 00882 template<typename _Alloc, typename _T1, typename _T2> 00883 tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>; 00884 template<typename _Alloc, typename... _UTypes> 00885 tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>; 00886 #endif 00887 00888 // Explicit specialization, zero-element tuple. 00889 template<> 00890 class tuple<> 00891 { 00892 public: 00893 void swap(tuple&) noexcept { /* no-op */ } 00894 // We need the default since we're going to define no-op 00895 // allocator constructors. 00896 tuple() = default; 00897 // No-op allocator constructors. 00898 template<typename _Alloc> 00899 tuple(allocator_arg_t, const _Alloc&) { } 00900 template<typename _Alloc> 00901 tuple(allocator_arg_t, const _Alloc&, const tuple&) { } 00902 }; 00903 00904 /// Partial specialization, 2-element tuple. 00905 /// Includes construction and assignment from a pair. 00906 template<typename _T1, typename _T2> 00907 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2> 00908 { 00909 typedef _Tuple_impl<0, _T1, _T2> _Inherited; 00910 00911 public: 00912 template <typename _U1 = _T1, 00913 typename _U2 = _T2, 00914 typename enable_if<__and_< 00915 __is_implicitly_default_constructible<_U1>, 00916 __is_implicitly_default_constructible<_U2>> 00917 ::value, bool>::type = true> 00918 00919 constexpr tuple() 00920 : _Inherited() { } 00921 00922 template <typename _U1 = _T1, 00923 typename _U2 = _T2, 00924 typename enable_if< 00925 __and_< 00926 is_default_constructible<_U1>, 00927 is_default_constructible<_U2>, 00928 __not_< 00929 __and_<__is_implicitly_default_constructible<_U1>, 00930 __is_implicitly_default_constructible<_U2>>>> 00931 ::value, bool>::type = false> 00932 00933 explicit constexpr tuple() 00934 : _Inherited() { } 00935 00936 // Shortcut for the cases where constructors taking _T1, _T2 00937 // need to be constrained. 00938 template<typename _Dummy> using _TCC = 00939 _TC<is_same<_Dummy, void>::value, _T1, _T2>; 00940 00941 template<typename _Dummy = void, typename 00942 enable_if<_TCC<_Dummy>::template 00943 _ConstructibleTuple<_T1, _T2>() 00944 && _TCC<_Dummy>::template 00945 _ImplicitlyConvertibleTuple<_T1, _T2>(), 00946 bool>::type = true> 00947 constexpr tuple(const _T1& __a1, const _T2& __a2) 00948 : _Inherited(__a1, __a2) { } 00949 00950 template<typename _Dummy = void, typename 00951 enable_if<_TCC<_Dummy>::template 00952 _ConstructibleTuple<_T1, _T2>() 00953 && !_TCC<_Dummy>::template 00954 _ImplicitlyConvertibleTuple<_T1, _T2>(), 00955 bool>::type = false> 00956 explicit constexpr tuple(const _T1& __a1, const _T2& __a2) 00957 : _Inherited(__a1, __a2) { } 00958 00959 // Shortcut for the cases where constructors taking _U1, _U2 00960 // need to be constrained. 00961 using _TMC = _TC<true, _T1, _T2>; 00962 00963 template<typename _U1, typename _U2, typename 00964 enable_if<_TMC::template 00965 _MoveConstructibleTuple<_U1, _U2>() 00966 && _TMC::template 00967 _ImplicitlyMoveConvertibleTuple<_U1, _U2>() 00968 && !is_same<typename decay<_U1>::type, 00969 allocator_arg_t>::value, 00970 bool>::type = true> 00971 constexpr tuple(_U1&& __a1, _U2&& __a2) 00972 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } 00973 00974 template<typename _U1, typename _U2, typename 00975 enable_if<_TMC::template 00976 _MoveConstructibleTuple<_U1, _U2>() 00977 && !_TMC::template 00978 _ImplicitlyMoveConvertibleTuple<_U1, _U2>() 00979 && !is_same<typename decay<_U1>::type, 00980 allocator_arg_t>::value, 00981 bool>::type = false> 00982 explicit constexpr tuple(_U1&& __a1, _U2&& __a2) 00983 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } 00984 00985 constexpr tuple(const tuple&) = default; 00986 00987 constexpr tuple(tuple&&) = default; 00988 00989 template<typename _U1, typename _U2, typename 00990 enable_if<_TMC::template 00991 _ConstructibleTuple<_U1, _U2>() 00992 && _TMC::template 00993 _ImplicitlyConvertibleTuple<_U1, _U2>(), 00994 bool>::type = true> 00995 constexpr tuple(const tuple<_U1, _U2>& __in) 00996 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { } 00997 00998 template<typename _U1, typename _U2, typename 00999 enable_if<_TMC::template 01000 _ConstructibleTuple<_U1, _U2>() 01001 && !_TMC::template 01002 _ImplicitlyConvertibleTuple<_U1, _U2>(), 01003 bool>::type = false> 01004 explicit constexpr tuple(const tuple<_U1, _U2>& __in) 01005 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { } 01006 01007 template<typename _U1, typename _U2, typename 01008 enable_if<_TMC::template 01009 _MoveConstructibleTuple<_U1, _U2>() 01010 && _TMC::template 01011 _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), 01012 bool>::type = true> 01013 constexpr tuple(tuple<_U1, _U2>&& __in) 01014 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } 01015 01016 template<typename _U1, typename _U2, typename 01017 enable_if<_TMC::template 01018 _MoveConstructibleTuple<_U1, _U2>() 01019 && !_TMC::template 01020 _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), 01021 bool>::type = false> 01022 explicit constexpr tuple(tuple<_U1, _U2>&& __in) 01023 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } 01024 01025 template<typename _U1, typename _U2, typename 01026 enable_if<_TMC::template 01027 _ConstructibleTuple<_U1, _U2>() 01028 && _TMC::template 01029 _ImplicitlyConvertibleTuple<_U1, _U2>(), 01030 bool>::type = true> 01031 constexpr tuple(const pair<_U1, _U2>& __in) 01032 : _Inherited(__in.first, __in.second) { } 01033 01034 template<typename _U1, typename _U2, typename 01035 enable_if<_TMC::template 01036 _ConstructibleTuple<_U1, _U2>() 01037 && !_TMC::template 01038 _ImplicitlyConvertibleTuple<_U1, _U2>(), 01039 bool>::type = false> 01040 explicit constexpr tuple(const pair<_U1, _U2>& __in) 01041 : _Inherited(__in.first, __in.second) { } 01042 01043 template<typename _U1, typename _U2, typename 01044 enable_if<_TMC::template 01045 _MoveConstructibleTuple<_U1, _U2>() 01046 && _TMC::template 01047 _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), 01048 bool>::type = true> 01049 constexpr tuple(pair<_U1, _U2>&& __in) 01050 : _Inherited(std::forward<_U1>(__in.first), 01051 std::forward<_U2>(__in.second)) { } 01052 01053 template<typename _U1, typename _U2, typename 01054 enable_if<_TMC::template 01055 _MoveConstructibleTuple<_U1, _U2>() 01056 && !_TMC::template 01057 _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), 01058 bool>::type = false> 01059 explicit constexpr tuple(pair<_U1, _U2>&& __in) 01060 : _Inherited(std::forward<_U1>(__in.first), 01061 std::forward<_U2>(__in.second)) { } 01062 01063 // Allocator-extended constructors. 01064 01065 template<typename _Alloc> 01066 tuple(allocator_arg_t __tag, const _Alloc& __a) 01067 : _Inherited(__tag, __a) { } 01068 01069 template<typename _Alloc, typename _Dummy = void, 01070 typename enable_if< 01071 _TCC<_Dummy>::template 01072 _ConstructibleTuple<_T1, _T2>() 01073 && _TCC<_Dummy>::template 01074 _ImplicitlyConvertibleTuple<_T1, _T2>(), 01075 bool>::type=true> 01076 01077 tuple(allocator_arg_t __tag, const _Alloc& __a, 01078 const _T1& __a1, const _T2& __a2) 01079 : _Inherited(__tag, __a, __a1, __a2) { } 01080 01081 template<typename _Alloc, typename _Dummy = void, 01082 typename enable_if< 01083 _TCC<_Dummy>::template 01084 _ConstructibleTuple<_T1, _T2>() 01085 && !_TCC<_Dummy>::template 01086 _ImplicitlyConvertibleTuple<_T1, _T2>(), 01087 bool>::type=false> 01088 01089 explicit tuple(allocator_arg_t __tag, const _Alloc& __a, 01090 const _T1& __a1, const _T2& __a2) 01091 : _Inherited(__tag, __a, __a1, __a2) { } 01092 01093 template<typename _Alloc, typename _U1, typename _U2, typename 01094 enable_if<_TMC::template 01095 _MoveConstructibleTuple<_U1, _U2>() 01096 && _TMC::template 01097 _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), 01098 bool>::type = true> 01099 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2) 01100 : _Inherited(__tag, __a, std::forward<_U1>(__a1), 01101 std::forward<_U2>(__a2)) { } 01102 01103 template<typename _Alloc, typename _U1, typename _U2, typename 01104 enable_if<_TMC::template 01105 _MoveConstructibleTuple<_U1, _U2>() 01106 && !_TMC::template 01107 _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), 01108 bool>::type = false> 01109 explicit tuple(allocator_arg_t __tag, const _Alloc& __a, 01110 _U1&& __a1, _U2&& __a2) 01111 : _Inherited(__tag, __a, std::forward<_U1>(__a1), 01112 std::forward<_U2>(__a2)) { } 01113 01114 template<typename _Alloc> 01115 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) 01116 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { } 01117 01118 template<typename _Alloc> 01119 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) 01120 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } 01121 01122 template<typename _Alloc, typename _U1, typename _U2, typename 01123 enable_if<_TMC::template 01124 _ConstructibleTuple<_U1, _U2>() 01125 && _TMC::template 01126 _ImplicitlyConvertibleTuple<_U1, _U2>(), 01127 bool>::type = true> 01128 tuple(allocator_arg_t __tag, const _Alloc& __a, 01129 const tuple<_U1, _U2>& __in) 01130 : _Inherited(__tag, __a, 01131 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) 01132 { } 01133 01134 template<typename _Alloc, typename _U1, typename _U2, typename 01135 enable_if<_TMC::template 01136 _ConstructibleTuple<_U1, _U2>() 01137 && !_TMC::template 01138 _ImplicitlyConvertibleTuple<_U1, _U2>(), 01139 bool>::type = false> 01140 explicit tuple(allocator_arg_t __tag, const _Alloc& __a, 01141 const tuple<_U1, _U2>& __in) 01142 : _Inherited(__tag, __a, 01143 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) 01144 { } 01145 01146 template<typename _Alloc, typename _U1, typename _U2, typename 01147 enable_if<_TMC::template 01148 _MoveConstructibleTuple<_U1, _U2>() 01149 && _TMC::template 01150 _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), 01151 bool>::type = true> 01152 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) 01153 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) 01154 { } 01155 01156 template<typename _Alloc, typename _U1, typename _U2, typename 01157 enable_if<_TMC::template 01158 _MoveConstructibleTuple<_U1, _U2>() 01159 && !_TMC::template 01160 _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), 01161 bool>::type = false> 01162 explicit tuple(allocator_arg_t __tag, const _Alloc& __a, 01163 tuple<_U1, _U2>&& __in) 01164 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) 01165 { } 01166 01167 template<typename _Alloc, typename _U1, typename _U2, typename 01168 enable_if<_TMC::template 01169 _ConstructibleTuple<_U1, _U2>() 01170 && _TMC::template 01171 _ImplicitlyConvertibleTuple<_U1, _U2>(), 01172 bool>::type = true> 01173 tuple(allocator_arg_t __tag, const _Alloc& __a, 01174 const pair<_U1, _U2>& __in) 01175 : _Inherited(__tag, __a, __in.first, __in.second) { } 01176 01177 template<typename _Alloc, typename _U1, typename _U2, typename 01178 enable_if<_TMC::template 01179 _ConstructibleTuple<_U1, _U2>() 01180 && !_TMC::template 01181 _ImplicitlyConvertibleTuple<_U1, _U2>(), 01182 bool>::type = false> 01183 explicit tuple(allocator_arg_t __tag, const _Alloc& __a, 01184 const pair<_U1, _U2>& __in) 01185 : _Inherited(__tag, __a, __in.first, __in.second) { } 01186 01187 template<typename _Alloc, typename _U1, typename _U2, typename 01188 enable_if<_TMC::template 01189 _MoveConstructibleTuple<_U1, _U2>() 01190 && _TMC::template 01191 _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), 01192 bool>::type = true> 01193 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) 01194 : _Inherited(__tag, __a, std::forward<_U1>(__in.first), 01195 std::forward<_U2>(__in.second)) { } 01196 01197 template<typename _Alloc, typename _U1, typename _U2, typename 01198 enable_if<_TMC::template 01199 _MoveConstructibleTuple<_U1, _U2>() 01200 && !_TMC::template 01201 _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), 01202 bool>::type = false> 01203 explicit tuple(allocator_arg_t __tag, const _Alloc& __a, 01204 pair<_U1, _U2>&& __in) 01205 : _Inherited(__tag, __a, std::forward<_U1>(__in.first), 01206 std::forward<_U2>(__in.second)) { } 01207 01208 tuple& 01209 operator=(const tuple& __in) 01210 { 01211 static_cast<_Inherited&>(*this) = __in; 01212 return *this; 01213 } 01214 01215 tuple& 01216 operator=(tuple&& __in) 01217 noexcept(is_nothrow_move_assignable<_Inherited>::value) 01218 { 01219 static_cast<_Inherited&>(*this) = std::move(__in); 01220 return *this; 01221 } 01222 01223 template<typename _U1, typename _U2> 01224 tuple& 01225 operator=(const tuple<_U1, _U2>& __in) 01226 { 01227 static_cast<_Inherited&>(*this) = __in; 01228 return *this; 01229 } 01230 01231 template<typename _U1, typename _U2> 01232 tuple& 01233 operator=(tuple<_U1, _U2>&& __in) 01234 { 01235 static_cast<_Inherited&>(*this) = std::move(__in); 01236 return *this; 01237 } 01238 01239 template<typename _U1, typename _U2> 01240 tuple& 01241 operator=(const pair<_U1, _U2>& __in) 01242 { 01243 this->_M_head(*this) = __in.first; 01244 this->_M_tail(*this)._M_head(*this) = __in.second; 01245 return *this; 01246 } 01247 01248 template<typename _U1, typename _U2> 01249 tuple& 01250 operator=(pair<_U1, _U2>&& __in) 01251 { 01252 this->_M_head(*this) = std::forward<_U1>(__in.first); 01253 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second); 01254 return *this; 01255 } 01256 01257 void 01258 swap(tuple& __in) 01259 noexcept(noexcept(__in._M_swap(__in))) 01260 { _Inherited::_M_swap(__in); } 01261 }; 01262 01263 01264 /// class tuple_size 01265 template<typename... _Elements> 01266 struct tuple_size<tuple<_Elements...>> 01267 : public integral_constant<std::size_t, sizeof...(_Elements)> { }; 01268 01269 #if __cplusplus > 201402L 01270 template <typename _Tp> 01271 inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value; 01272 #endif 01273 01274 /** 01275 * Recursive case for tuple_element: strip off the first element in 01276 * the tuple and retrieve the (i-1)th element of the remaining tuple. 01277 */ 01278 template<std::size_t __i, typename _Head, typename... _Tail> 01279 struct tuple_element<__i, tuple<_Head, _Tail...> > 01280 : tuple_element<__i - 1, tuple<_Tail...> > { }; 01281 01282 /** 01283 * Basis case for tuple_element: The first element is the one we're seeking. 01284 */ 01285 template<typename _Head, typename... _Tail> 01286 struct tuple_element<0, tuple<_Head, _Tail...> > 01287 { 01288 typedef _Head type; 01289 }; 01290 01291 /** 01292 * Error case for tuple_element: invalid index. 01293 */ 01294 template<size_t __i> 01295 struct tuple_element<__i, tuple<>> 01296 { 01297 static_assert(__i < tuple_size<tuple<>>::value, 01298 "tuple index is in range"); 01299 }; 01300 01301 template<std::size_t __i, typename _Head, typename... _Tail> 01302 constexpr _Head& 01303 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 01304 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } 01305 01306 template<std::size_t __i, typename _Head, typename... _Tail> 01307 constexpr const _Head& 01308 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 01309 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } 01310 01311 /// Return a reference to the ith element of a tuple. 01312 template<std::size_t __i, typename... _Elements> 01313 constexpr __tuple_element_t<__i, tuple<_Elements...>>& 01314 get(tuple<_Elements...>& __t) noexcept 01315 { return std::__get_helper<__i>(__t); } 01316 01317 /// Return a const reference to the ith element of a const tuple. 01318 template<std::size_t __i, typename... _Elements> 01319 constexpr const __tuple_element_t<__i, tuple<_Elements...>>& 01320 get(const tuple<_Elements...>& __t) noexcept 01321 { return std::__get_helper<__i>(__t); } 01322 01323 /// Return an rvalue reference to the ith element of a tuple rvalue. 01324 template<std::size_t __i, typename... _Elements> 01325 constexpr __tuple_element_t<__i, tuple<_Elements...>>&& 01326 get(tuple<_Elements...>&& __t) noexcept 01327 { 01328 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; 01329 return std::forward<__element_type&&>(std::get<__i>(__t)); 01330 } 01331 01332 /// Return a const rvalue reference to the ith element of a const tuple rvalue. 01333 template<std::size_t __i, typename... _Elements> 01334 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&& 01335 get(const tuple<_Elements...>&& __t) noexcept 01336 { 01337 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; 01338 return std::forward<const __element_type&&>(std::get<__i>(__t)); 01339 } 01340 01341 #if __cplusplus > 201103L 01342 01343 #define __cpp_lib_tuples_by_type 201304 01344 01345 template<typename _Head, size_t __i, typename... _Tail> 01346 constexpr _Head& 01347 __get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 01348 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } 01349 01350 template<typename _Head, size_t __i, typename... _Tail> 01351 constexpr const _Head& 01352 __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 01353 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } 01354 01355 /// Return a reference to the unique element of type _Tp of a tuple. 01356 template <typename _Tp, typename... _Types> 01357 constexpr _Tp& 01358 get(tuple<_Types...>& __t) noexcept 01359 { return std::__get_helper2<_Tp>(__t); } 01360 01361 /// Return a reference to the unique element of type _Tp of a tuple rvalue. 01362 template <typename _Tp, typename... _Types> 01363 constexpr _Tp&& 01364 get(tuple<_Types...>&& __t) noexcept 01365 { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } 01366 01367 /// Return a const reference to the unique element of type _Tp of a tuple. 01368 template <typename _Tp, typename... _Types> 01369 constexpr const _Tp& 01370 get(const tuple<_Types...>& __t) noexcept 01371 { return std::__get_helper2<_Tp>(__t); } 01372 01373 /// Return a const reference to the unique element of type _Tp of 01374 /// a const tuple rvalue. 01375 template <typename _Tp, typename... _Types> 01376 constexpr const _Tp&& 01377 get(const tuple<_Types...>&& __t) noexcept 01378 { return std::forward<const _Tp&&>(std::__get_helper2<_Tp>(__t)); } 01379 #endif 01380 01381 // This class performs the comparison operations on tuples 01382 template<typename _Tp, typename _Up, size_t __i, size_t __size> 01383 struct __tuple_compare 01384 { 01385 static constexpr bool 01386 __eq(const _Tp& __t, const _Up& __u) 01387 { 01388 return bool(std::get<__i>(__t) == std::get<__i>(__u)) 01389 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u); 01390 } 01391 01392 static constexpr bool 01393 __less(const _Tp& __t, const _Up& __u) 01394 { 01395 return bool(std::get<__i>(__t) < std::get<__i>(__u)) 01396 || (!bool(std::get<__i>(__u) < std::get<__i>(__t)) 01397 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u)); 01398 } 01399 }; 01400 01401 template<typename _Tp, typename _Up, size_t __size> 01402 struct __tuple_compare<_Tp, _Up, __size, __size> 01403 { 01404 static constexpr bool 01405 __eq(const _Tp&, const _Up&) { return true; } 01406 01407 static constexpr bool 01408 __less(const _Tp&, const _Up&) { return false; } 01409 }; 01410 01411 template<typename... _TElements, typename... _UElements> 01412 constexpr bool 01413 operator==(const tuple<_TElements...>& __t, 01414 const tuple<_UElements...>& __u) 01415 { 01416 static_assert(sizeof...(_TElements) == sizeof...(_UElements), 01417 "tuple objects can only be compared if they have equal sizes."); 01418 using __compare = __tuple_compare<tuple<_TElements...>, 01419 tuple<_UElements...>, 01420 0, sizeof...(_TElements)>; 01421 return __compare::__eq(__t, __u); 01422 } 01423 01424 template<typename... _TElements, typename... _UElements> 01425 constexpr bool 01426 operator<(const tuple<_TElements...>& __t, 01427 const tuple<_UElements...>& __u) 01428 { 01429 static_assert(sizeof...(_TElements) == sizeof...(_UElements), 01430 "tuple objects can only be compared if they have equal sizes."); 01431 using __compare = __tuple_compare<tuple<_TElements...>, 01432 tuple<_UElements...>, 01433 0, sizeof...(_TElements)>; 01434 return __compare::__less(__t, __u); 01435 } 01436 01437 template<typename... _TElements, typename... _UElements> 01438 constexpr bool 01439 operator!=(const tuple<_TElements...>& __t, 01440 const tuple<_UElements...>& __u) 01441 { return !(__t == __u); } 01442 01443 template<typename... _TElements, typename... _UElements> 01444 constexpr bool 01445 operator>(const tuple<_TElements...>& __t, 01446 const tuple<_UElements...>& __u) 01447 { return __u < __t; } 01448 01449 template<typename... _TElements, typename... _UElements> 01450 constexpr bool 01451 operator<=(const tuple<_TElements...>& __t, 01452 const tuple<_UElements...>& __u) 01453 { return !(__u < __t); } 01454 01455 template<typename... _TElements, typename... _UElements> 01456 constexpr bool 01457 operator>=(const tuple<_TElements...>& __t, 01458 const tuple<_UElements...>& __u) 01459 { return !(__t < __u); } 01460 01461 // NB: DR 705. 01462 template<typename... _Elements> 01463 constexpr tuple<typename __decay_and_strip<_Elements>::__type...> 01464 make_tuple(_Elements&&... __args) 01465 { 01466 typedef tuple<typename __decay_and_strip<_Elements>::__type...> 01467 __result_type; 01468 return __result_type(std::forward<_Elements>(__args)...); 01469 } 01470 01471 // _GLIBCXX_RESOLVE_LIB_DEFECTS 01472 // 2275. Why is forward_as_tuple not constexpr? 01473 template<typename... _Elements> 01474 constexpr tuple<_Elements&&...> 01475 forward_as_tuple(_Elements&&... __args) noexcept 01476 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } 01477 01478 template<size_t, typename, typename, size_t> 01479 struct __make_tuple_impl; 01480 01481 template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm> 01482 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm> 01483 : __make_tuple_impl<_Idx + 1, 01484 tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>, 01485 _Tuple, _Nm> 01486 { }; 01487 01488 template<std::size_t _Nm, typename _Tuple, typename... _Tp> 01489 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm> 01490 { 01491 typedef tuple<_Tp...> __type; 01492 }; 01493 01494 template<typename _Tuple> 01495 struct __do_make_tuple 01496 : __make_tuple_impl<0, tuple<>, _Tuple, std::tuple_size<_Tuple>::value> 01497 { }; 01498 01499 // Returns the std::tuple equivalent of a tuple-like type. 01500 template<typename _Tuple> 01501 struct __make_tuple 01502 : public __do_make_tuple<typename std::remove_cv 01503 <typename std::remove_reference<_Tuple>::type>::type> 01504 { }; 01505 01506 // Combines several std::tuple's into a single one. 01507 template<typename...> 01508 struct __combine_tuples; 01509 01510 template<> 01511 struct __combine_tuples<> 01512 { 01513 typedef tuple<> __type; 01514 }; 01515 01516 template<typename... _Ts> 01517 struct __combine_tuples<tuple<_Ts...>> 01518 { 01519 typedef tuple<_Ts...> __type; 01520 }; 01521 01522 template<typename... _T1s, typename... _T2s, typename... _Rem> 01523 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...> 01524 { 01525 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>, 01526 _Rem...>::__type __type; 01527 }; 01528 01529 // Computes the result type of tuple_cat given a set of tuple-like types. 01530 template<typename... _Tpls> 01531 struct __tuple_cat_result 01532 { 01533 typedef typename __combine_tuples 01534 <typename __make_tuple<_Tpls>::__type...>::__type __type; 01535 }; 01536 01537 // Helper to determine the index set for the first tuple-like 01538 // type of a given set. 01539 template<typename...> 01540 struct __make_1st_indices; 01541 01542 template<> 01543 struct __make_1st_indices<> 01544 { 01545 typedef std::_Index_tuple<> __type; 01546 }; 01547 01548 template<typename _Tp, typename... _Tpls> 01549 struct __make_1st_indices<_Tp, _Tpls...> 01550 { 01551 typedef typename std::_Build_index_tuple<std::tuple_size< 01552 typename std::remove_reference<_Tp>::type>::value>::__type __type; 01553 }; 01554 01555 // Performs the actual concatenation by step-wise expanding tuple-like 01556 // objects into the elements, which are finally forwarded into the 01557 // result tuple. 01558 template<typename _Ret, typename _Indices, typename... _Tpls> 01559 struct __tuple_concater; 01560 01561 template<typename _Ret, std::size_t... _Is, typename _Tp, typename... _Tpls> 01562 struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...> 01563 { 01564 template<typename... _Us> 01565 static constexpr _Ret 01566 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us) 01567 { 01568 typedef typename __make_1st_indices<_Tpls...>::__type __idx; 01569 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next; 01570 return __next::_S_do(std::forward<_Tpls>(__tps)..., 01571 std::forward<_Us>(__us)..., 01572 std::get<_Is>(std::forward<_Tp>(__tp))...); 01573 } 01574 }; 01575 01576 template<typename _Ret> 01577 struct __tuple_concater<_Ret, std::_Index_tuple<>> 01578 { 01579 template<typename... _Us> 01580 static constexpr _Ret 01581 _S_do(_Us&&... __us) 01582 { 01583 return _Ret(std::forward<_Us>(__us)...); 01584 } 01585 }; 01586 01587 /// tuple_cat 01588 template<typename... _Tpls, typename = typename 01589 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type> 01590 constexpr auto 01591 tuple_cat(_Tpls&&... __tpls) 01592 -> typename __tuple_cat_result<_Tpls...>::__type 01593 { 01594 typedef typename __tuple_cat_result<_Tpls...>::__type __ret; 01595 typedef typename __make_1st_indices<_Tpls...>::__type __idx; 01596 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater; 01597 return __concater::_S_do(std::forward<_Tpls>(__tpls)...); 01598 } 01599 01600 // _GLIBCXX_RESOLVE_LIB_DEFECTS 01601 // 2301. Why is tie not constexpr? 01602 /// tie 01603 template<typename... _Elements> 01604 constexpr tuple<_Elements&...> 01605 tie(_Elements&... __args) noexcept 01606 { return tuple<_Elements&...>(__args...); } 01607 01608 /// swap 01609 template<typename... _Elements> 01610 inline 01611 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 01612 // Constrained free swap overload, see p0185r1 01613 typename enable_if<__and_<__is_swappable<_Elements>...>::value 01614 >::type 01615 #else 01616 void 01617 #endif 01618 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y) 01619 noexcept(noexcept(__x.swap(__y))) 01620 { __x.swap(__y); } 01621 01622 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 01623 template<typename... _Elements> 01624 typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type 01625 swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete; 01626 #endif 01627 01628 // A class (and instance) which can be used in 'tie' when an element 01629 // of a tuple is not required. 01630 // _GLIBCXX14_CONSTEXPR 01631 // 2933. PR for LWG 2773 could be clearer 01632 struct _Swallow_assign 01633 { 01634 template<class _Tp> 01635 _GLIBCXX14_CONSTEXPR const _Swallow_assign& 01636 operator=(const _Tp&) const 01637 { return *this; } 01638 }; 01639 01640 // _GLIBCXX_RESOLVE_LIB_DEFECTS 01641 // 2773. Making std::ignore constexpr 01642 _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{}; 01643 01644 /// Partial specialization for tuples 01645 template<typename... _Types, typename _Alloc> 01646 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { }; 01647 01648 // See stl_pair.h... 01649 template<class _T1, class _T2> 01650 template<typename... _Args1, typename... _Args2> 01651 inline 01652 pair<_T1, _T2>:: 01653 pair(piecewise_construct_t, 01654 tuple<_Args1...> __first, tuple<_Args2...> __second) 01655 : pair(__first, __second, 01656 typename _Build_index_tuple<sizeof...(_Args1)>::__type(), 01657 typename _Build_index_tuple<sizeof...(_Args2)>::__type()) 01658 { } 01659 01660 template<class _T1, class _T2> 01661 template<typename... _Args1, std::size_t... _Indexes1, 01662 typename... _Args2, std::size_t... _Indexes2> 01663 inline 01664 pair<_T1, _T2>:: 01665 pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2, 01666 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>) 01667 : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...), 01668 second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...) 01669 { } 01670 01671 #if __cplusplus > 201402L 01672 # define __cpp_lib_apply 201603 01673 01674 template <typename _Fn, typename _Tuple, size_t... _Idx> 01675 constexpr decltype(auto) 01676 __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>) 01677 { 01678 return std::__invoke(std::forward<_Fn>(__f), 01679 std::get<_Idx>(std::forward<_Tuple>(__t))...); 01680 } 01681 01682 template <typename _Fn, typename _Tuple> 01683 constexpr decltype(auto) 01684 apply(_Fn&& __f, _Tuple&& __t) 01685 { 01686 using _Indices = make_index_sequence<tuple_size_v<decay_t<_Tuple>>>; 01687 return std::__apply_impl(std::forward<_Fn>(__f), 01688 std::forward<_Tuple>(__t), 01689 _Indices{}); 01690 } 01691 01692 #define __cpp_lib_make_from_tuple 201606 01693 01694 template <typename _Tp, typename _Tuple, size_t... _Idx> 01695 constexpr _Tp 01696 __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>) 01697 { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); } 01698 01699 template <typename _Tp, typename _Tuple> 01700 constexpr _Tp 01701 make_from_tuple(_Tuple&& __t) 01702 { 01703 return __make_from_tuple_impl<_Tp>( 01704 std::forward<_Tuple>(__t), 01705 make_index_sequence<tuple_size_v<decay_t<_Tuple>>>{}); 01706 } 01707 #endif // C++17 01708 01709 /// @} 01710 01711 _GLIBCXX_END_NAMESPACE_VERSION 01712 } // namespace std 01713 01714 #endif // C++11 01715 01716 #endif // _GLIBCXX_TUPLE