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 | |