1227825Stheraven// -*- C++ -*-
2227825Stheraven//===----------------------------------------------------------------------===//
3227825Stheraven//
4227825Stheraven//                     The LLVM Compiler Infrastructure
5227825Stheraven//
6227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
7227825Stheraven// Source Licenses. See LICENSE.TXT for details.
8227825Stheraven//
9227825Stheraven//===----------------------------------------------------------------------===//
10227825Stheraven
11227825Stheraven#ifndef _LIBCPP___TUPLE
12227825Stheraven#define _LIBCPP___TUPLE
13227825Stheraven
14227825Stheraven#include <__config>
15227825Stheraven#include <cstddef>
16227825Stheraven#include <type_traits>
17227825Stheraven
18227825Stheraven#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19227825Stheraven#pragma GCC system_header
20227825Stheraven#endif
21227825Stheraven
22227825Stheraven
23227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
24227825Stheraven
25261272Sdimtemplate <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size;
26227825Stheraven
27227825Stheraventemplate <class _Tp>
28261272Sdimclass _LIBCPP_TYPE_VIS_ONLY tuple_size<const _Tp>
29227825Stheraven    : public tuple_size<_Tp> {};
30227825Stheraven
31227825Stheraventemplate <class _Tp>
32261272Sdimclass _LIBCPP_TYPE_VIS_ONLY tuple_size<volatile _Tp>
33227825Stheraven    : public tuple_size<_Tp> {};
34227825Stheraven
35227825Stheraventemplate <class _Tp>
36261272Sdimclass _LIBCPP_TYPE_VIS_ONLY tuple_size<const volatile _Tp>
37227825Stheraven    : public tuple_size<_Tp> {};
38227825Stheraven
39261272Sdimtemplate <size_t _Ip, class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_element;
40227825Stheraven
41227825Stheraventemplate <size_t _Ip, class _Tp>
42261272Sdimclass _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, const _Tp>
43227825Stheraven{
44227825Stheravenpublic:
45227825Stheraven    typedef typename add_const<typename tuple_element<_Ip, _Tp>::type>::type type;
46227825Stheraven};
47227825Stheraven
48227825Stheraventemplate <size_t _Ip, class _Tp>
49261272Sdimclass _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, volatile _Tp>
50227825Stheraven{
51227825Stheravenpublic:
52227825Stheraven    typedef typename add_volatile<typename tuple_element<_Ip, _Tp>::type>::type type;
53227825Stheraven};
54227825Stheraven
55227825Stheraventemplate <size_t _Ip, class _Tp>
56261272Sdimclass _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, const volatile _Tp>
57227825Stheraven{
58227825Stheravenpublic:
59227825Stheraven    typedef typename add_cv<typename tuple_element<_Ip, _Tp>::type>::type type;
60227825Stheraven};
61227825Stheraven
62227825Stheraventemplate <class _Tp> struct __tuple_like : false_type {};
63227825Stheraven
64227825Stheraventemplate <class _Tp> struct __tuple_like<const _Tp> : public __tuple_like<_Tp> {};
65227825Stheraventemplate <class _Tp> struct __tuple_like<volatile _Tp> : public __tuple_like<_Tp> {};
66227825Stheraventemplate <class _Tp> struct __tuple_like<const volatile _Tp> : public __tuple_like<_Tp> {};
67227825Stheraven
68288943Sdim// tuple specializations
69288943Sdim
70288943Sdim#if !defined(_LIBCPP_HAS_NO_VARIADICS)
71288943Sdimtemplate <class ..._Tp> class _LIBCPP_TYPE_VIS_ONLY tuple;
72288943Sdim
73227825Stheraventemplate <class... _Tp> struct __tuple_like<tuple<_Tp...> > : true_type {};
74227825Stheraven
75227825Stheraventemplate <size_t _Ip, class ..._Tp>
76261272Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
77227825Stheraventypename tuple_element<_Ip, tuple<_Tp...> >::type&
78227825Stheravenget(tuple<_Tp...>&) _NOEXCEPT;
79227825Stheraven
80227825Stheraventemplate <size_t _Ip, class ..._Tp>
81261272Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
82227825Stheravenconst typename tuple_element<_Ip, tuple<_Tp...> >::type&
83227825Stheravenget(const tuple<_Tp...>&) _NOEXCEPT;
84227825Stheraven
85227825Stheraventemplate <size_t _Ip, class ..._Tp>
86261272Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
87227825Stheraventypename tuple_element<_Ip, tuple<_Tp...> >::type&&
88227825Stheravenget(tuple<_Tp...>&&) _NOEXCEPT;
89300770Sdim
90300770Sdimtemplate <size_t _Ip, class ..._Tp>
91300770Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
92300770Sdimconst typename tuple_element<_Ip, tuple<_Tp...> >::type&&
93300770Sdimget(const tuple<_Tp...>&&) _NOEXCEPT;
94288943Sdim#endif
95227825Stheraven
96288943Sdim// pair specializations
97288943Sdim
98288943Sdimtemplate <class _T1, class _T2> struct _LIBCPP_TYPE_VIS_ONLY pair;
99288943Sdim
100288943Sdimtemplate <class _T1, class _T2> struct __tuple_like<pair<_T1, _T2> > : true_type {};
101288943Sdim
102227825Stheraventemplate <size_t _Ip, class _T1, class _T2>
103261272Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
104227825Stheraventypename tuple_element<_Ip, pair<_T1, _T2> >::type&
105227825Stheravenget(pair<_T1, _T2>&) _NOEXCEPT;
106227825Stheraven
107227825Stheraventemplate <size_t _Ip, class _T1, class _T2>
108261272Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
109227825Stheravenconst typename tuple_element<_Ip, pair<_T1, _T2> >::type&
110227825Stheravenget(const pair<_T1, _T2>&) _NOEXCEPT;
111227825Stheraven
112288943Sdim#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES)
113227825Stheraventemplate <size_t _Ip, class _T1, class _T2>
114261272Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
115227825Stheraventypename tuple_element<_Ip, pair<_T1, _T2> >::type&&
116227825Stheravenget(pair<_T1, _T2>&&) _NOEXCEPT;
117300770Sdim
118300770Sdimtemplate <size_t _Ip, class _T1, class _T2>
119300770Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
120300770Sdimconst typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
121300770Sdimget(const pair<_T1, _T2>&&) _NOEXCEPT;
122288943Sdim#endif
123227825Stheraven
124288943Sdim// array specializations
125288943Sdim
126288943Sdimtemplate <class _Tp, size_t _Size> struct _LIBCPP_TYPE_VIS_ONLY array;
127288943Sdim
128288943Sdimtemplate <class _Tp, size_t _Size> struct __tuple_like<array<_Tp, _Size> > : true_type {};
129288943Sdim
130227825Stheraventemplate <size_t _Ip, class _Tp, size_t _Size>
131261272Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
132227825Stheraven_Tp&
133227825Stheravenget(array<_Tp, _Size>&) _NOEXCEPT;
134227825Stheraven
135227825Stheraventemplate <size_t _Ip, class _Tp, size_t _Size>
136261272Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
137227825Stheravenconst _Tp&
138227825Stheravenget(const array<_Tp, _Size>&) _NOEXCEPT;
139227825Stheraven
140288943Sdim#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES)
141227825Stheraventemplate <size_t _Ip, class _Tp, size_t _Size>
142261272Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
143227825Stheraven_Tp&&
144227825Stheravenget(array<_Tp, _Size>&&) _NOEXCEPT;
145300770Sdim
146300770Sdimtemplate <size_t _Ip, class _Tp, size_t _Size>
147300770Sdim_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
148300770Sdimconst _Tp&&
149300770Sdimget(const array<_Tp, _Size>&&) _NOEXCEPT;
150288943Sdim#endif
151227825Stheraven
152288943Sdim#if !defined(_LIBCPP_HAS_NO_VARIADICS)
153288943Sdim
154227825Stheraven// __make_tuple_indices
155227825Stheraven
156227825Stheraventemplate <size_t...> struct __tuple_indices {};
157227825Stheraven
158227825Stheraventemplate <size_t _Sp, class _IntTuple, size_t _Ep>
159227825Stheravenstruct __make_indices_imp;
160227825Stheraven
161227825Stheraventemplate <size_t _Sp, size_t ..._Indices, size_t _Ep>
162227825Stheravenstruct __make_indices_imp<_Sp, __tuple_indices<_Indices...>, _Ep>
163227825Stheraven{
164227825Stheraven    typedef typename __make_indices_imp<_Sp+1, __tuple_indices<_Indices..., _Sp>, _Ep>::type type;
165227825Stheraven};
166227825Stheraven
167227825Stheraventemplate <size_t _Ep, size_t ..._Indices>
168227825Stheravenstruct __make_indices_imp<_Ep, __tuple_indices<_Indices...>, _Ep>
169227825Stheraven{
170227825Stheraven    typedef __tuple_indices<_Indices...> type;
171227825Stheraven};
172227825Stheraven
173227825Stheraventemplate <size_t _Ep, size_t _Sp = 0>
174227825Stheravenstruct __make_tuple_indices
175227825Stheraven{
176227825Stheraven    static_assert(_Sp <= _Ep, "__make_tuple_indices input error");
177227825Stheraven    typedef typename __make_indices_imp<_Sp, __tuple_indices<>, _Ep>::type type;
178227825Stheraven};
179227825Stheraven
180227825Stheraven// __tuple_types
181227825Stheraven
182227825Stheraventemplate <class ..._Tp> struct __tuple_types {};
183227825Stheraven
184227825Stheraventemplate <size_t _Ip>
185261272Sdimclass _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, __tuple_types<> >
186227825Stheraven{
187227825Stheravenpublic:
188227825Stheraven    static_assert(_Ip == 0, "tuple_element index out of range");
189227825Stheraven    static_assert(_Ip != 0, "tuple_element index out of range");
190227825Stheraven};
191227825Stheraven
192227825Stheraventemplate <class _Hp, class ..._Tp>
193261272Sdimclass _LIBCPP_TYPE_VIS_ONLY tuple_element<0, __tuple_types<_Hp, _Tp...> >
194227825Stheraven{
195227825Stheravenpublic:
196227825Stheraven    typedef _Hp type;
197227825Stheraven};
198227825Stheraven
199227825Stheraventemplate <size_t _Ip, class _Hp, class ..._Tp>
200261272Sdimclass _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, __tuple_types<_Hp, _Tp...> >
201227825Stheraven{
202227825Stheravenpublic:
203227825Stheraven    typedef typename tuple_element<_Ip-1, __tuple_types<_Tp...> >::type type;
204227825Stheraven};
205227825Stheraven
206227825Stheraventemplate <class ..._Tp>
207261272Sdimclass _LIBCPP_TYPE_VIS_ONLY tuple_size<__tuple_types<_Tp...> >
208227825Stheraven    : public integral_constant<size_t, sizeof...(_Tp)>
209227825Stheraven{
210227825Stheraven};
211227825Stheraven
212227825Stheraventemplate <class... _Tp> struct __tuple_like<__tuple_types<_Tp...> > : true_type {};
213227825Stheraven
214227825Stheraven// __make_tuple_types
215227825Stheraven
216227825Stheraven// __make_tuple_types<_Tuple<_Types...>, _Ep, _Sp>::type is a
217227825Stheraven// __tuple_types<_Types...> using only those _Types in the range [_Sp, _Ep).
218227825Stheraven// _Sp defaults to 0 and _Ep defaults to tuple_size<_Tuple>.  If _Tuple is a
219227825Stheraven// lvalue_reference type, then __tuple_types<_Types&...> is the result.
220227825Stheraven
221227825Stheraventemplate <class _TupleTypes, class _Tp, size_t _Sp, size_t _Ep>
222227825Stheravenstruct __make_tuple_types_imp;
223227825Stheraven
224227825Stheraventemplate <class ..._Types, class _Tp, size_t _Sp, size_t _Ep>
225227825Stheravenstruct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Sp, _Ep>
226227825Stheraven{
227227825Stheraven    typedef typename remove_reference<_Tp>::type _Tpr;
228227825Stheraven    typedef typename __make_tuple_types_imp<__tuple_types<_Types...,
229227825Stheraven                                            typename conditional<is_lvalue_reference<_Tp>::value,
230227825Stheraven                                                typename tuple_element<_Sp, _Tpr>::type&,
231227825Stheraven                                                typename tuple_element<_Sp, _Tpr>::type>::type>,
232227825Stheraven                                            _Tp, _Sp+1, _Ep>::type type;
233227825Stheraven};
234227825Stheraven
235227825Stheraventemplate <class ..._Types, class _Tp, size_t _Ep>
236227825Stheravenstruct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Ep, _Ep>
237227825Stheraven{
238227825Stheraven    typedef __tuple_types<_Types...> type;
239227825Stheraven};
240227825Stheraven
241227825Stheraventemplate <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value, size_t _Sp = 0>
242227825Stheravenstruct __make_tuple_types
243227825Stheraven{
244227825Stheraven    static_assert(_Sp <= _Ep, "__make_tuple_types input error");
245227825Stheraven    typedef typename __make_tuple_types_imp<__tuple_types<>, _Tp, _Sp, _Ep>::type type;
246227825Stheraven};
247227825Stheraven
248227825Stheraven// __tuple_convertible
249227825Stheraven
250276792Sdimtemplate <class, class>
251227825Stheravenstruct __tuple_convertible_imp : public false_type {};
252227825Stheraven
253227825Stheraventemplate <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
254276792Sdimstruct __tuple_convertible_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> >
255227825Stheraven    : public integral_constant<bool,
256234959Stheraven                               is_convertible<_Tp0, _Up0>::value &&
257276792Sdim                               __tuple_convertible_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {};
258227825Stheraven
259227825Stheraventemplate <>
260276792Sdimstruct __tuple_convertible_imp<__tuple_types<>, __tuple_types<> >
261227825Stheraven    : public true_type {};
262227825Stheraven
263276792Sdimtemplate <bool, class, class>
264276792Sdimstruct __tuple_convertible_apply : public false_type {};
265276792Sdim
266276792Sdimtemplate <class _Tp, class _Up>
267276792Sdimstruct __tuple_convertible_apply<true, _Tp, _Up>
268276792Sdim  : public __tuple_convertible_imp<
269276792Sdim      typename __make_tuple_types<_Tp>::type
270276792Sdim    , typename __make_tuple_types<_Up>::type
271276792Sdim    >
272276792Sdim{};
273276792Sdim
274227825Stheraventemplate <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
275227825Stheraven                                bool = __tuple_like<_Up>::value>
276227825Stheravenstruct __tuple_convertible
277227825Stheraven    : public false_type {};
278227825Stheraven
279227825Stheraventemplate <class _Tp, class _Up>
280227825Stheravenstruct __tuple_convertible<_Tp, _Up, true, true>
281276792Sdim    : public __tuple_convertible_apply<tuple_size<typename remove_reference<_Tp>::type>::value ==
282276792Sdim                                     tuple_size<_Up>::value, _Tp, _Up>
283227825Stheraven{};
284227825Stheraven
285234959Stheraven// __tuple_constructible
286234959Stheraven
287276792Sdimtemplate <class, class>
288234959Stheravenstruct __tuple_constructible_imp : public false_type {};
289234959Stheraven
290234959Stheraventemplate <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
291276792Sdimstruct __tuple_constructible_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> >
292234959Stheraven    : public integral_constant<bool,
293234959Stheraven                               is_constructible<_Up0, _Tp0>::value &&
294276792Sdim                               __tuple_constructible_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {};
295234959Stheraven
296234959Stheraventemplate <>
297276792Sdimstruct __tuple_constructible_imp<__tuple_types<>, __tuple_types<> >
298234959Stheraven    : public true_type {};
299234959Stheraven
300276792Sdimtemplate <bool _SameSize, class, class>
301276792Sdimstruct __tuple_constructible_apply : public false_type {};
302276792Sdim
303276792Sdimtemplate <class _Tp, class _Up>
304276792Sdimstruct __tuple_constructible_apply<true, _Tp, _Up>
305276792Sdim  : public __tuple_constructible_imp<
306276792Sdim      typename __make_tuple_types<_Tp>::type
307276792Sdim    , typename __make_tuple_types<_Up>::type
308276792Sdim    >
309276792Sdim{};
310276792Sdim
311234959Stheraventemplate <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
312234959Stheraven                                bool = __tuple_like<_Up>::value>
313234959Stheravenstruct __tuple_constructible
314234959Stheraven    : public false_type {};
315234959Stheraven
316234959Stheraventemplate <class _Tp, class _Up>
317234959Stheravenstruct __tuple_constructible<_Tp, _Up, true, true>
318276792Sdim    : public __tuple_constructible_apply<tuple_size<typename remove_reference<_Tp>::type>::value ==
319276792Sdim                                     tuple_size<_Up>::value, _Tp, _Up>
320234959Stheraven{};
321234959Stheraven
322227825Stheraven// __tuple_assignable
323227825Stheraven
324276792Sdimtemplate <class, class>
325227825Stheravenstruct __tuple_assignable_imp : public false_type {};
326227825Stheraven
327227825Stheraventemplate <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
328276792Sdimstruct __tuple_assignable_imp<__tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...> >
329227825Stheraven    : public integral_constant<bool,
330227825Stheraven                               is_assignable<_Up0&, _Tp0>::value &&
331276792Sdim                               __tuple_assignable_imp<__tuple_types<_Tp...>, __tuple_types<_Up...> >::value> {};
332227825Stheraven
333227825Stheraventemplate <>
334276792Sdimstruct __tuple_assignable_imp<__tuple_types<>, __tuple_types<> >
335227825Stheraven    : public true_type {};
336227825Stheraven
337276792Sdimtemplate <bool, class, class>
338276792Sdimstruct __tuple_assignable_apply : public false_type {};
339276792Sdim
340276792Sdimtemplate <class _Tp, class _Up>
341276792Sdimstruct __tuple_assignable_apply<true, _Tp, _Up>
342276792Sdim  : __tuple_assignable_imp<
343276792Sdim      typename __make_tuple_types<_Tp>::type
344276792Sdim    , typename __make_tuple_types<_Up>::type
345276792Sdim    >
346276792Sdim{};
347276792Sdim
348227825Stheraventemplate <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
349227825Stheraven                                bool = __tuple_like<_Up>::value>
350227825Stheravenstruct __tuple_assignable
351227825Stheraven    : public false_type {};
352227825Stheraven
353227825Stheraventemplate <class _Tp, class _Up>
354227825Stheravenstruct __tuple_assignable<_Tp, _Up, true, true>
355276792Sdim    : public __tuple_assignable_apply<tuple_size<typename remove_reference<_Tp>::type>::value ==
356276792Sdim                                    tuple_size<_Up>::value, _Tp, _Up>
357227825Stheraven{};
358227825Stheraven
359288943Sdim#endif  // _LIBCPP_HAS_NO_VARIADICS
360288943Sdim
361227825Stheraven_LIBCPP_END_NAMESPACE_STD
362227825Stheraven
363227825Stheraven#endif  // _LIBCPP___TUPLE
364