blob: 642cff8651899aeb2a28248d2485462626a3dc4b [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
24#else
25
26_LIBCPP_BEGIN_NAMESPACE_STD
27
28template <class _Tp> class tuple_size;
29template <size_t _Ip, class _Tp> class tuple_element;
30
31template <class ..._Tp> class tuple;
32template <class _T1, class _T2> class pair;
33template <class _Tp, size_t _Size> struct array;
34
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
44
45template <size_t _Ip, class ..._Tp>
46typename tuple_element<_Ip, tuple<_Tp...>>::type&
47get(tuple<_Tp...>&);
48
49template <size_t _Ip, class ..._Tp>
50const typename tuple_element<_Ip, tuple<_Tp...>>::type&
51get(const tuple<_Tp...>&);
52
53template <size_t _Ip, class _T1, class _T2>
54typename tuple_element<_Ip, pair<_T1, _T2> >::type&
55get(pair<_T1, _T2>&);
56
57template <size_t _Ip, class _T1, class _T2>
58const typename tuple_element<_Ip, pair<_T1, _T2> >::type&
59get(const pair<_T1, _T2>&);
60
61template <size_t _Ip, class _Tp, size_t _Size>
62_Tp&
63get(array<_Tp, _Size>&);
64
65template <size_t _Ip, class _Tp, size_t _Size>
66const _Tp&
67get(const array<_Tp, _Size>&);
68
69// __make_tuple_indices
70
71template <size_t...> struct __tuple_indices {};
72
73template <size_t _Sp, class _IntTuple, size_t _Ep>
74struct __make_indices_imp;
75
76template <size_t _Sp, size_t ..._Indices, size_t _Ep>
77struct __make_indices_imp<_Sp, __tuple_indices<_Indices...>, _Ep>
78{
79 typedef typename __make_indices_imp<_Sp+1, __tuple_indices<_Indices..., _Sp>, _Ep>::type type;
80};
81
82template <size_t _Ep, size_t ..._Indices>
83struct __make_indices_imp<_Ep, __tuple_indices<_Indices...>, _Ep>
84{
85 typedef __tuple_indices<_Indices...> type;
86};
87
88template <size_t _Ep, size_t _Sp = 0>
89struct __make_tuple_indices
90{
91 static_assert(_Sp <= _Ep, "__make_tuple_indices input error");
92 typedef typename __make_indices_imp<_Sp, __tuple_indices<>, _Ep>::type type;
93};
94
95// __tuple_types
96
97template <class ..._Tp> struct __tuple_types {};
98
99template <size_t _Ip>
100class tuple_element<_Ip, __tuple_types<>>
101{
102public:
103 static_assert(_Ip == 0, "tuple_element index out of range");
104 static_assert(_Ip != 0, "tuple_element index out of range");
105};
106
107template <class _Hp, class ..._Tp>
108class tuple_element<0, __tuple_types<_Hp, _Tp...>>
109{
110public:
111 typedef _Hp type;
112};
113
114template <size_t _Ip, class _Hp, class ..._Tp>
115class tuple_element<_Ip, __tuple_types<_Hp, _Tp...>>
116{
117public:
118 typedef typename tuple_element<_Ip-1, __tuple_types<_Tp...>>::type type;
119};
120
121template <class ..._Tp>
122class tuple_size<__tuple_types<_Tp...>>
123 : public integral_constant<size_t, sizeof...(_Tp)>
124{
125};
126
127template <class... _Tp> struct __tuple_like<__tuple_types<_Tp...>> : true_type {};
128
129// __make_tuple_types
130
131template <class _TupleTypes, class _Tp, size_t _Sp, size_t _Ep>
132struct __make_tuple_types_imp;
133
134template <class ..._Types, class _Tp, size_t _Sp, size_t _Ep>
135struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Sp, _Ep>
136{
137 typedef typename remove_reference<_Tp>::type _Tpr;
138 typedef typename __make_tuple_types_imp<__tuple_types<_Types...,
139 typename conditional<is_reference<_Tp>::value,
140 typename tuple_element<_Sp, _Tpr>::type&,
141 typename tuple_element<_Sp, _Tpr>::type>::type>,
142 _Tp, _Sp+1, _Ep>::type type;
143};
144
145template <class ..._Types, class _Tp, size_t _Ep>
146struct __make_tuple_types_imp<__tuple_types<_Types...>, _Tp, _Ep, _Ep>
147{
148 typedef __tuple_types<_Types...> type;
149};
150
151template <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value, size_t _Sp = 0>
152struct __make_tuple_types
153{
154 static_assert(_Sp <= _Ep, "__make_tuple_types input error");
155 typedef typename __make_tuple_types_imp<__tuple_types<>, _Tp, _Sp, _Ep>::type type;
156};
157
158// __make_assignable_types
159
160template <class _Tuple, class _Tp, size_t _Sp, size_t _Ep>
161struct __make_assignable_types_imp;
162
163template <class ..._Types, class _Tp, size_t _Sp, size_t _Ep>
164struct __make_assignable_types_imp<__tuple_types<_Types...>, _Tp, _Sp, _Ep>
165{
166 typedef typename __make_assignable_types_imp<__tuple_types<_Types...,
167 typename remove_reference<typename tuple_element<_Sp, _Tp>::type>::type>,
168 _Tp, _Sp+1, _Ep>::type type;
169};
170
171template <class ..._Types, class _Tp, size_t _Ep>
172struct __make_assignable_types_imp<__tuple_types<_Types...>, _Tp, _Ep, _Ep>
173{
174 typedef __tuple_types<_Types...> type;
175};
176
177template <class _Tp, size_t _Ep = tuple_size<typename remove_reference<_Tp>::type>::value, size_t _Sp = 0>
178struct __make_assignable_types
179{
180 static_assert(_Sp <= _Ep, "__make_assignable_types input error");
181 typedef typename __make_assignable_types_imp<__tuple_types<>, typename remove_reference<_Tp>::type, _Sp, _Ep>::type type;
182};
183
184// __tuple_convertible
185
186template <bool, class _Tp, class _Up>
187struct __tuple_convertible_imp : public false_type {};
188
189template <class _Tp0, class ..._Tp, class _Up0, class ..._Up>
190struct __tuple_convertible_imp<true, __tuple_types<_Tp0, _Tp...>, __tuple_types<_Up0, _Up...>>
191 : public integral_constant<bool,
192 is_convertible<_Tp0, _Up0>::value &&
193 __tuple_convertible_imp<true, __tuple_types<_Tp...>, __tuple_types<_Up...>>::value> {};
194
195template <>
196struct __tuple_convertible_imp<true, __tuple_types<>, __tuple_types<>>
197 : public true_type {};
198
199template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
200 bool = __tuple_like<_Up>::value>
201struct __tuple_convertible
202 : public false_type {};
203
204template <class _Tp, class _Up>
205struct __tuple_convertible<_Tp, _Up, true, true>
206 : public __tuple_convertible_imp<tuple_size<typename remove_reference<_Tp>::type>::value ==
207 tuple_size<_Up>::value,
208 typename __make_tuple_types<_Tp>::type, typename __make_tuple_types<_Up>::type>
209{};
210
211// __tuple_assignable
212
213template <class _Tp, class _Up, bool = __tuple_like<typename remove_reference<_Tp>::type>::value,
214 bool = __tuple_like<_Up>::value>
215struct __tuple_assignable
216 : public false_type {};
217
218template <class _Tp, class _Up>
219struct __tuple_assignable<_Tp, _Up, true, true>
220 : public __tuple_convertible_imp<tuple_size<typename remove_reference<_Tp>::type>::value ==
221 tuple_size<_Up>::value,
222 typename __make_tuple_types<_Tp>::type, typename __make_assignable_types<_Up>::type>
223{};
224
225_LIBCPP_END_NAMESPACE_STD
226
227#endif // _LIBCPP_HAS_NO_VARIADICS
228
229#endif // _LIBCPP___TUPLE