blob: e10f8d78b5707b2100da1c8b8a72796ba575c184 [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
Howard Hinnante049cc52010-09-27 17:54:17 +0000130// __make_tuple_types<_Tuple<_Types...>, _Ep, _Sp>::type is a
131// __tuple_types<_Types...> using only those _Types in the range [_Sp, _Ep).
132// _Sp defaults to 0 and _Ep defaults to tuple_size<_Tuple>. If _Tuple is a
133// lvalue_reference type, then __tuple_types<_Types&...> is the result.
134
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000135template <class _TupleTypes, class _Tp, size_t _Sp, size_t _Ep>
136struct __make_tuple_types_imp;
137
138template <class ..._Types, class _Tp, size_t _Sp, size_t _Ep>
139struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Sp, _Ep>
140{
141 typedef typename remove_reference<_Tp>::type _Tpr;
142 typedef typename __make_tuple_types_imp<__tuple_types<_Types...,
Howard Hinnante049cc52010-09-27 17:54:17 +0000143 typename conditional<is_lvalue_reference<_Tp>::value,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000144 typename tuple_element<_Sp, _Tpr>::type&,
145 typename tuple_element<_Sp, _Tpr>::type>::type>,
146 _Tp, _Sp+1, _Ep>::type type;
147};
148
149template <class ..._Types, class _Tp, size_t _Ep>
150struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Ep, _Ep>
151{
152 typedef __tuple_types<_Types...> type;
153};
154
155template <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value, size_t _Sp = 0>
156struct __make_tuple_types
157{
158 static_assert(_Sp <= _Ep, "__make_tuple_types input error");
159 typedef typename __make_tuple_types_imp<__tuple_types<>, _Tp, _Sp, _Ep>::type type;
160};
161
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000162// __tuple_convertible
163
164template <bool, class _Tp, class _Up>
165struct __tuple_convertible_imp : public false_type {};
166
167template <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
168struct __tuple_convertible_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...>>
169 : public integral_constant<bool,
170 is_convertible<_Tp0, _Up0>::value &&
171 __tuple_convertible_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...>>::value> {};
172
173template <>
174struct __tuple_convertible_imp<true, __tuple_types<>, __tuple_types<>>
175 : public true_type {};
176
177template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
178 bool = __tuple_like<_Up>::value>
179struct __tuple_convertible
180 : public false_type {};
181
182template <class _Tp, class _Up>
183struct __tuple_convertible<_Tp, _Up, true, true>
184 : public __tuple_convertible_imp<tuple_size<typename remove_reference<_Tp>::type>::value ==
185 tuple_size<_Up>::value,
186 typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type>
187{};
188
189// __tuple_assignable
190
Howard Hinnante049cc52010-09-27 17:54:17 +0000191template <bool, class _Tp, class _Up>
192struct __tuple_assignable_imp : public false_type {};
193
194template <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
195struct __tuple_assignable_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...>>
196 : public integral_constant<bool,
197 __is_assignable<_Up0&, _Tp0>::value &&
198 __tuple_assignable_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...>>::value> {};
199
200template <>
201struct __tuple_assignable_imp<true, __tuple_types<>, __tuple_types<>>
202 : public true_type {};
203
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000204template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
205 bool = __tuple_like<_Up>::value>
206struct __tuple_assignable
207 : public false_type {};
208
209template <class _Tp, class _Up>
210struct __tuple_assignable<_Tp, _Up, true, true>
Howard Hinnante049cc52010-09-27 17:54:17 +0000211 : public __tuple_assignable_imp<tuple_size<typename remove_reference<_Tp>::type>::value ==
212 tuple_size<_Up>::value,
213 typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000214{};
215
216_LIBCPP_END_NAMESPACE_STD
217
218#endif // _LIBCPP_HAS_NO_VARIADICS
219
220#endif // _LIBCPP___TUPLE