• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef BOOST_MP11_LIST_HPP_INCLUDED
2 #define BOOST_MP11_LIST_HPP_INCLUDED
3 
4 //  Copyright 2015-2017 Peter Dimov.
5 //
6 //  Distributed under the Boost Software License, Version 1.0.
7 //
8 //  See accompanying file LICENSE_1_0.txt or copy at
9 //  http://www.boost.org/LICENSE_1_0.txt
10 
11 #include <boost/mp11/integral.hpp>
12 #include <boost/mp11/detail/mp_list.hpp>
13 #include <boost/mp11/detail/mp_is_list.hpp>
14 #include <boost/mp11/detail/mp_append.hpp>
15 #include <boost/mp11/detail/config.hpp>
16 #include <type_traits>
17 
18 namespace boost
19 {
20 namespace mp11
21 {
22 
23 // mp_list_c<T, I...>
24 template<class T, T... I> using mp_list_c = mp_list<std::integral_constant<T, I>...>;
25 
26 // mp_is_list<L>
27 //   in detail/mp_is_list.hpp
28 
29 // mp_size<L>
30 namespace detail
31 {
32 
33 template<class L> struct mp_size_impl
34 {
35 // An error "no type named 'type'" here means that the argument to mp_size is not a list
36 };
37 
38 template<template<class...> class L, class... T> struct mp_size_impl<L<T...>>
39 {
40     using type = mp_size_t<sizeof...(T)>;
41 };
42 
43 } // namespace detail
44 
45 template<class L> using mp_size = typename detail::mp_size_impl<L>::type;
46 
47 // mp_empty<L>
48 template<class L> using mp_empty = mp_bool< mp_size<L>::value == 0 >;
49 
50 // mp_assign<L1, L2>
51 namespace detail
52 {
53 
54 template<class L1, class L2> struct mp_assign_impl;
55 
56 template<template<class...> class L1, class... T, template<class...> class L2, class... U> struct mp_assign_impl<L1<T...>, L2<U...>>
57 {
58     using type = L1<U...>;
59 };
60 
61 } // namespace detail
62 
63 template<class L1, class L2> using mp_assign = typename detail::mp_assign_impl<L1, L2>::type;
64 
65 // mp_clear<L>
66 template<class L> using mp_clear = mp_assign<L, mp_list<>>;
67 
68 // mp_front<L>
69 namespace detail
70 {
71 
72 template<class L> struct mp_front_impl
73 {
74 // An error "no type named 'type'" here means that the argument to mp_front
75 // is either not a list, or is an empty list
76 };
77 
78 template<template<class...> class L, class T1, class... T> struct mp_front_impl<L<T1, T...>>
79 {
80     using type = T1;
81 };
82 
83 } // namespace detail
84 
85 template<class L> using mp_front = typename detail::mp_front_impl<L>::type;
86 
87 // mp_pop_front<L>
88 namespace detail
89 {
90 
91 template<class L> struct mp_pop_front_impl
92 {
93 // An error "no type named 'type'" here means that the argument to mp_pop_front
94 // is either not a list, or is an empty list
95 };
96 
97 template<template<class...> class L, class T1, class... T> struct mp_pop_front_impl<L<T1, T...>>
98 {
99     using type = L<T...>;
100 };
101 
102 } // namespace detail
103 
104 template<class L> using mp_pop_front = typename detail::mp_pop_front_impl<L>::type;
105 
106 // mp_first<L>
107 template<class L> using mp_first = mp_front<L>;
108 
109 // mp_rest<L>
110 template<class L> using mp_rest = mp_pop_front<L>;
111 
112 // mp_second<L>
113 namespace detail
114 {
115 
116 template<class L> struct mp_second_impl
117 {
118 // An error "no type named 'type'" here means that the argument to mp_second
119 // is either not a list, or has fewer than two elements
120 };
121 
122 template<template<class...> class L, class T1, class T2, class... T> struct mp_second_impl<L<T1, T2, T...>>
123 {
124     using type = T2;
125 };
126 
127 } // namespace detail
128 
129 template<class L> using mp_second = typename detail::mp_second_impl<L>::type;
130 
131 // mp_third<L>
132 namespace detail
133 {
134 
135 template<class L> struct mp_third_impl
136 {
137 // An error "no type named 'type'" here means that the argument to mp_third
138 // is either not a list, or has fewer than three elements
139 };
140 
141 template<template<class...> class L, class T1, class T2, class T3, class... T> struct mp_third_impl<L<T1, T2, T3, T...>>
142 {
143     using type = T3;
144 };
145 
146 } // namespace detail
147 
148 template<class L> using mp_third = typename detail::mp_third_impl<L>::type;
149 
150 // mp_push_front<L, T...>
151 namespace detail
152 {
153 
154 template<class L, class... T> struct mp_push_front_impl
155 {
156 // An error "no type named 'type'" here means that the first argument to mp_push_front is not a list
157 };
158 
159 template<template<class...> class L, class... U, class... T> struct mp_push_front_impl<L<U...>, T...>
160 {
161     using type = L<T..., U...>;
162 };
163 
164 } // namespace detail
165 
166 template<class L, class... T> using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;
167 
168 // mp_push_back<L, T...>
169 namespace detail
170 {
171 
172 template<class L, class... T> struct mp_push_back_impl
173 {
174 // An error "no type named 'type'" here means that the first argument to mp_push_back is not a list
175 };
176 
177 template<template<class...> class L, class... U, class... T> struct mp_push_back_impl<L<U...>, T...>
178 {
179     using type = L<U..., T...>;
180 };
181 
182 } // namespace detail
183 
184 template<class L, class... T> using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type;
185 
186 // mp_rename<L, B>
187 namespace detail
188 {
189 
190 template<class A, template<class...> class B> struct mp_rename_impl
191 {
192 // An error "no type named 'type'" here means that the first argument to mp_rename is not a list
193 };
194 
195 template<template<class...> class A, class... T, template<class...> class B> struct mp_rename_impl<A<T...>, B>
196 {
197     using type = B<T...>;
198 };
199 
200 } // namespace detail
201 
202 template<class A, template<class...> class B> using mp_rename = typename detail::mp_rename_impl<A, B>::type;
203 
204 template<template<class...> class F, class L> using mp_apply = typename detail::mp_rename_impl<L, F>::type;
205 
206 template<class Q, class L> using mp_apply_q = typename detail::mp_rename_impl<L, Q::template fn>::type;
207 
208 // mp_replace_front<L, T>
209 namespace detail
210 {
211 
212 template<class L, class T> struct mp_replace_front_impl
213 {
214 // An error "no type named 'type'" here means that the first argument to mp_replace_front
215 // is either not a list, or is an empty list
216 };
217 
218 template<template<class...> class L, class U1, class... U, class T> struct mp_replace_front_impl<L<U1, U...>, T>
219 {
220     using type = L<T, U...>;
221 };
222 
223 } // namespace detail
224 
225 template<class L, class T> using mp_replace_front = typename detail::mp_replace_front_impl<L, T>::type;
226 
227 // mp_replace_first<L, T>
228 template<class L, class T> using mp_replace_first = typename detail::mp_replace_front_impl<L, T>::type;
229 
230 // mp_replace_second<L, T>
231 namespace detail
232 {
233 
234 template<class L, class T> struct mp_replace_second_impl
235 {
236 // An error "no type named 'type'" here means that the first argument to mp_replace_second
237 // is either not a list, or has fewer than two elements
238 };
239 
240 template<template<class...> class L, class U1, class U2, class... U, class T> struct mp_replace_second_impl<L<U1, U2, U...>, T>
241 {
242     using type = L<U1, T, U...>;
243 };
244 
245 } // namespace detail
246 
247 template<class L, class T> using mp_replace_second = typename detail::mp_replace_second_impl<L, T>::type;
248 
249 // mp_replace_third<L, T>
250 namespace detail
251 {
252 
253 template<class L, class T> struct mp_replace_third_impl
254 {
255 // An error "no type named 'type'" here means that the first argument to mp_replace_third
256 // is either not a list, or has fewer than three elements
257 };
258 
259 template<template<class...> class L, class U1, class U2, class U3, class... U, class T> struct mp_replace_third_impl<L<U1, U2, U3, U...>, T>
260 {
261     using type = L<U1, U2, T, U...>;
262 };
263 
264 } // namespace detail
265 
266 template<class L, class T> using mp_replace_third = typename detail::mp_replace_third_impl<L, T>::type;
267 
268 // mp_transform_front<L, F>
269 namespace detail
270 {
271 
272 template<class L, template<class...> class F> struct mp_transform_front_impl
273 {
274 // An error "no type named 'type'" here means that the first argument to mp_transform_front
275 // is either not a list, or is an empty list
276 };
277 
278 template<template<class...> class L, class U1, class... U, template<class...> class F> struct mp_transform_front_impl<L<U1, U...>, F>
279 {
280     using type = L<F<U1>, U...>;
281 };
282 
283 } // namespace detail
284 
285 template<class L, template<class...> class F> using mp_transform_front = typename detail::mp_transform_front_impl<L, F>::type;
286 template<class L, class Q> using mp_transform_front_q = mp_transform_front<L, Q::template fn>;
287 
288 // mp_transform_first<L, F>
289 template<class L, template<class...> class F> using mp_transform_first = typename detail::mp_transform_front_impl<L, F>::type;
290 template<class L, class Q> using mp_transform_first_q = mp_transform_first<L, Q::template fn>;
291 
292 // mp_transform_second<L, F>
293 namespace detail
294 {
295 
296 template<class L, template<class...> class F> struct mp_transform_second_impl
297 {
298 // An error "no type named 'type'" here means that the first argument to mp_transform_second
299 // is either not a list, or has fewer than two elements
300 };
301 
302 template<template<class...> class L, class U1, class U2, class... U, template<class...> class F> struct mp_transform_second_impl<L<U1, U2, U...>, F>
303 {
304     using type = L<U1, F<U2>, U...>;
305 };
306 
307 } // namespace detail
308 
309 template<class L, template<class...> class F> using mp_transform_second = typename detail::mp_transform_second_impl<L, F>::type;
310 template<class L, class Q> using mp_transform_second_q = mp_transform_second<L, Q::template fn>;
311 
312 // mp_transform_third<L, F>
313 namespace detail
314 {
315 
316 template<class L, template<class...> class F> struct mp_transform_third_impl
317 {
318 // An error "no type named 'type'" here means that the first argument to mp_transform_third
319 // is either not a list, or has fewer than three elements
320 };
321 
322 template<template<class...> class L, class U1, class U2, class U3, class... U, template<class...> class F> struct mp_transform_third_impl<L<U1, U2, U3, U...>, F>
323 {
324     using type = L<U1, U2, F<U3>, U...>;
325 };
326 
327 } // namespace detail
328 
329 template<class L, template<class...> class F> using mp_transform_third = typename detail::mp_transform_third_impl<L, F>::type;
330 template<class L, class Q> using mp_transform_third_q = mp_transform_third<L, Q::template fn>;
331 
332 } // namespace mp11
333 } // namespace boost
334 
335 #endif // #ifndef BOOST_MP11_LIST_HPP_INCLUDED
336