blob: 7fa74148fd3fd488f4eeeab66c8c5eb913c890f7 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
6// This file is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP___TUPLE
12#define _LIBCPP___TUPLE
13
14#include <__config>
15#include <cstddef>
16#include <type_traits>
17
18#pragma GCC system_header
19
20#ifdef _LIBCPP_HAS_NO_VARIADICS
21
22#include <__tuple_03>
23
Howard Hinnant324bb032010-08-22 00:02:43 +000024#else // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000025
26_LIBCPP_BEGIN_NAMESPACE_STD
27
Howard Hinnant333f50d2010-09-21 20:16:37 +000028template <class _Tp> class _LIBCPP_VISIBLE tuple_size;
29template <size_t _Ip, class _Tp> class _LIBCPP_VISIBLE tuple_element;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000030
Howard Hinnant333f50d2010-09-21 20:16:37 +000031template <class ..._Tp> class _LIBCPP_VISIBLE tuple;
32template <class _T1, class _T2> class _LIBCPP_VISIBLE pair;
33template <class _Tp, size_t _Size> struct _LIBCPP_VISIBLE array;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000034
35template <class _Tp> struct __tuple_like : false_type {};
36
37template <class... _Tp> struct __tuple_like<tuple<_Tp...>> : true_type {};
38template <class... _Tp> struct __tuple_like<const tuple<_Tp...>> : true_type {};
39template <class _T1, class _T2> struct __tuple_like<pair<_T1, _T2> > : true_type {};
40template <class _T1, class _T2> struct __tuple_like<const pair<_T1, _T2> > : true_type {};
41template <class _Tp, size_t _Size> struct __tuple_like<array<_Tp, _Size> > : true_type {};
42template <class _Tp, size_t _Size> struct __tuple_like<const array<_Tp, _Size> > : true_type {};
43
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000044template <size_t _Ip, class ..._Tp>
45typename tuple_element<_Ip, tuple<_Tp...>>::type&
46get(tuple<_Tp...>&);
47
48template <size_t _Ip, class ..._Tp>
49const typename tuple_element<_Ip, tuple<_Tp...>>::type&
50get(const tuple<_Tp...>&);
51
52template <size_t _Ip, class _T1, class _T2>
53typename tuple_element<_Ip, pair<_T1, _T2> >::type&
54get(pair<_T1, _T2>&);
55
56template <size_t _Ip, class _T1, class _T2>
57const typename tuple_element<_Ip, pair<_T1, _T2> >::type&
58get(const pair<_T1, _T2>&);
59
60template <size_t _Ip, class _Tp, size_t _Size>
61_Tp&
62get(array<_Tp, _Size>&);
63
64template <size_t _Ip, class _Tp, size_t _Size>
65const _Tp&
66get(const array<_Tp, _Size>&);
67
68// __make_tuple_indices
69
70template <size_t...> struct __tuple_indices {};
71
72template <size_t _Sp, class _IntTuple, size_t _Ep>
73struct __make_indices_imp;
74
75template <size_t _Sp, size_t ..._Indices, size_t _Ep>
76struct __make_indices_imp<_Sp, __tuple_indices<_Indices...>, _Ep>
77{
78 typedef typename __make_indices_imp<_Sp+1, __tuple_indices<_Indices..., _Sp>, _Ep>::type type;
79};
80
81template <size_t _Ep, size_t ..._Indices>
82struct __make_indices_imp<_Ep, __tuple_indices<_Indices...>, _Ep>
83{
84 typedef __tuple_indices<_Indices...> type;
85};
86
87template <size_t _Ep, size_t _Sp = 0>
88struct __make_tuple_indices
89{
90 static_assert(_Sp <= _Ep, "__make_tuple_indices input error");
91 typedef typename __make_indices_imp<_Sp, __tuple_indices<>, _Ep>::type type;
92};
93
94// __tuple_types
95
96template <class ..._Tp> struct __tuple_types {};
97
98template <size_t _Ip>
Howard Hinnant333f50d2010-09-21 20:16:37 +000099class _LIBCPP_VISIBLE tuple_element<_Ip, __tuple_types<>>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000100{
101public:
102 static_assert(_Ip == 0, "tuple_element index out of range");
103 static_assert(_Ip != 0, "tuple_element index out of range");
104};
105
106template <class _Hp, class ..._Tp>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000107class _LIBCPP_VISIBLE tuple_element<0, __tuple_types<_Hp, _Tp...>>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000108{
109public:
110 typedef _Hp type;
111};
112
113template <size_t _Ip, class _Hp, class ..._Tp>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000114class _LIBCPP_VISIBLE tuple_element<_Ip, __tuple_types<_Hp, _Tp...>>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000115{
116public:
117 typedef typename tuple_element<_Ip-1, __tuple_types<_Tp...>>::type type;
118};
119
120template <class ..._Tp>
Howard Hinnant333f50d2010-09-21 20:16:37 +0000121class _LIBCPP_VISIBLE tuple_size<__tuple_types<_Tp...>>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000122 : public integral_constant<size_t, sizeof...(_Tp)>
123{
124};
125
126template <class... _Tp> struct __tuple_like<__tuple_types<_Tp...>> : true_type {};
127
128// __make_tuple_types
129
130template <class _TupleTypes, class _Tp, size_t _Sp, size_t _Ep>
131struct __make_tuple_types_imp;
132
133template <class ..._Types, class _Tp, size_t _Sp, size_t _Ep>
134struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Sp, _Ep>
135{
136 typedef typename remove_reference<_Tp>::type _Tpr;
137 typedef typename __make_tuple_types_imp<__tuple_types<_Types...,
138 typename conditional<is_reference<_Tp>::value,
139 typename tuple_element<_Sp, _Tpr>::type&,
140 typename tuple_element<_Sp, _Tpr>::type>::type>,
141 _Tp, _Sp+1, _Ep>::type type;
142};
143
144template <class ..._Types, class _Tp, size_t _Ep>
145struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Ep, _Ep>
146{
147 typedef __tuple_types<_Types...> type;
148};
149
150template <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value, size_t _Sp = 0>
151struct __make_tuple_types
152{
153 static_assert(_Sp <= _Ep, "__make_tuple_types input error");
154 typedef typename __make_tuple_types_imp<__tuple_types<>, _Tp, _Sp, _Ep>::type type;
155};
156
157// __make_assignable_types
158
159template <class _Tuple, class _Tp, size_t _Sp, size_t _Ep>
160struct __make_assignable_types_imp;
161
162template <class ..._Types, class _Tp, size_t _Sp, size_t _Ep>
163struct __make_assignable_types_imp<__tuple_types<_Types...>, _Tp, _Sp, _Ep>
164{
165 typedef typename __make_assignable_types_imp<__tuple_types<_Types...,
166 typename remove_reference<typename tuple_element<_Sp, _Tp>::type>::type>,
167 _Tp, _Sp+1, _Ep>::type type;
168};
169
170template <class ..._Types, class _Tp, size_t _Ep>
171struct __make_assignable_types_imp<__tuple_types<_Types...>, _Tp, _Ep, _Ep>
172{
173 typedef __tuple_types<_Types...> type;
174};
175
176template <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value, size_t _Sp = 0>
177struct __make_assignable_types
178{
179 static_assert(_Sp <= _Ep, "__make_assignable_types input error");
180 typedef typename __make_assignable_types_imp<__tuple_types<>, typename remove_reference<_Tp>::type, _Sp, _Ep>::type type;
181};
182
183// __tuple_convertible
184
185template <bool, class _Tp, class _Up>
186struct __tuple_convertible_imp : public false_type {};
187
188template <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
189struct __tuple_convertible_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...>>
190 : public integral_constant<bool,
191 is_convertible<_Tp0, _Up0>::value &&
192 __tuple_convertible_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...>>::value> {};
193
194template <>
195struct __tuple_convertible_imp<true, __tuple_types<>, __tuple_types<>>
196 : public true_type {};
197
198template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
199 bool = __tuple_like<_Up>::value>
200struct __tuple_convertible
201 : public false_type {};
202
203template <class _Tp, class _Up>
204struct __tuple_convertible<_Tp, _Up, true, true>
205 : public __tuple_convertible_imp<tuple_size<typename remove_reference<_Tp>::type>::value ==
206 tuple_size<_Up>::value,
207 typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type>
208{};
209
210// __tuple_assignable
211
212template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
213 bool = __tuple_like<_Up>::value>
214struct __tuple_assignable
215 : public false_type {};
216
217template <class _Tp, class _Up>
218struct __tuple_assignable<_Tp, _Up, true, true>
219 : public __tuple_convertible_imp<tuple_size<typename remove_reference<_Tp>::type>::value ==
220 tuple_size<_Up>::value,
221 typename __make_tuple_types<_Tp>::type, typename __make_assignable_types<_Up>::type>
222{};
223
224_LIBCPP_END_NAMESPACE_STD
225
226#endif // _LIBCPP_HAS_NO_VARIADICS
227
228#endif // _LIBCPP___TUPLE