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