1 | #ifndef BOOST_MP11_LIST_HPP_INCLUDED |
2 | #define BOOST_MP11_LIST_HPP_INCLUDED |
3 | |
4 | // Copyright 2015-2023 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_list_v.hpp> |
14 | #include <boost/mp11/detail/mp_is_list.hpp> |
15 | #include <boost/mp11/detail/mp_is_value_list.hpp> |
16 | #include <boost/mp11/detail/mp_front.hpp> |
17 | #include <boost/mp11/detail/mp_rename.hpp> |
18 | #include <boost/mp11/detail/mp_append.hpp> |
19 | #include <boost/mp11/detail/config.hpp> |
20 | #include <type_traits> |
21 | |
22 | #if defined(_MSC_VER) || defined(__GNUC__) |
23 | # pragma push_macro( "I" ) |
24 | # undef I |
25 | #endif |
26 | |
27 | namespace boost |
28 | { |
29 | namespace mp11 |
30 | { |
31 | |
32 | // mp_list<T...> |
33 | // in detail/mp_list.hpp |
34 | |
35 | // mp_list_c<T, I...> |
36 | template<class T, T... I> using mp_list_c = mp_list<std::integral_constant<T, I>...>; |
37 | |
38 | // mp_list_v<A...> |
39 | // in detail/mp_list_v.hpp |
40 | |
41 | // mp_is_list<L> |
42 | // in detail/mp_is_list.hpp |
43 | |
44 | // mp_is_value_list<L> |
45 | // in detail/mp_is_value_list.hpp |
46 | |
47 | // mp_size<L> |
48 | namespace detail |
49 | { |
50 | |
51 | template<class L> struct mp_size_impl |
52 | { |
53 | // An error "no type named 'type'" here means that the argument to mp_size is not a list |
54 | }; |
55 | |
56 | template<template<class...> class L, class... T> struct mp_size_impl<L<T...>> |
57 | { |
58 | using type = mp_size_t<sizeof...(T)>; |
59 | }; |
60 | |
61 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
62 | |
63 | template<template<auto...> class L, auto... A> struct mp_size_impl<L<A...>> |
64 | { |
65 | using type = mp_size_t<sizeof...(A)>; |
66 | }; |
67 | |
68 | #endif |
69 | |
70 | } // namespace detail |
71 | |
72 | template<class L> using mp_size = typename detail::mp_size_impl<L>::type; |
73 | |
74 | // mp_empty<L> |
75 | template<class L> using mp_empty = mp_bool< mp_size<L>::value == 0 >; |
76 | |
77 | // mp_assign<L1, L2> |
78 | namespace detail |
79 | { |
80 | |
81 | template<class L1, class L2> struct mp_assign_impl |
82 | { |
83 | // An error "no type named 'type'" here means that the arguments to mp_assign aren't lists |
84 | }; |
85 | |
86 | template<template<class...> class L1, class... T, template<class...> class L2, class... U> struct mp_assign_impl<L1<T...>, L2<U...>> |
87 | { |
88 | using type = L1<U...>; |
89 | }; |
90 | |
91 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
92 | |
93 | template<template<auto...> class L1, auto... A, template<class...> class L2, class... U> struct mp_assign_impl<L1<A...>, L2<U...>> |
94 | { |
95 | using type = L1<U::value...>; |
96 | }; |
97 | |
98 | template<template<class...> class L1, class... T, template<auto...> class L2, auto... B> struct mp_assign_impl<L1<T...>, L2<B...>> |
99 | { |
100 | using type = L1<mp_value<B>...>; |
101 | }; |
102 | |
103 | template<template<auto...> class L1, auto... A, template<auto...> class L2, auto... B> struct mp_assign_impl<L1<A...>, L2<B...>> |
104 | { |
105 | using type = L1<B...>; |
106 | }; |
107 | |
108 | #endif |
109 | |
110 | } // namespace detail |
111 | |
112 | template<class L1, class L2> using mp_assign = typename detail::mp_assign_impl<L1, L2>::type; |
113 | |
114 | // mp_clear<L> |
115 | template<class L> using mp_clear = mp_assign<L, mp_list<>>; |
116 | |
117 | // mp_front<L> |
118 | // in detail/mp_front.hpp |
119 | |
120 | // mp_pop_front<L> |
121 | namespace detail |
122 | { |
123 | |
124 | template<class L> struct mp_pop_front_impl |
125 | { |
126 | // An error "no type named 'type'" here means that the argument to mp_pop_front |
127 | // is either not a list, or is an empty list |
128 | }; |
129 | |
130 | template<template<class...> class L, class T1, class... T> struct mp_pop_front_impl<L<T1, T...>> |
131 | { |
132 | using type = L<T...>; |
133 | }; |
134 | |
135 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
136 | |
137 | template<template<auto...> class L, auto A1, auto... A> struct mp_pop_front_impl<L<A1, A...>> |
138 | { |
139 | using type = L<A...>; |
140 | }; |
141 | |
142 | #endif |
143 | |
144 | } // namespace detail |
145 | |
146 | template<class L> using mp_pop_front = typename detail::mp_pop_front_impl<L>::type; |
147 | |
148 | // mp_first<L> |
149 | template<class L> using mp_first = mp_front<L>; |
150 | |
151 | // mp_rest<L> |
152 | template<class L> using mp_rest = mp_pop_front<L>; |
153 | |
154 | // mp_second<L> |
155 | namespace detail |
156 | { |
157 | |
158 | template<class L> struct mp_second_impl |
159 | { |
160 | // An error "no type named 'type'" here means that the argument to mp_second |
161 | // is either not a list, or has fewer than two elements |
162 | }; |
163 | |
164 | template<template<class...> class L, class T1, class T2, class... T> struct mp_second_impl<L<T1, T2, T...>> |
165 | { |
166 | using type = T2; |
167 | }; |
168 | |
169 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
170 | |
171 | template<template<auto...> class L, auto A1, auto A2, auto... A> struct mp_second_impl<L<A1, A2, A...>> |
172 | { |
173 | using type = mp_value<A2>; |
174 | }; |
175 | |
176 | #endif |
177 | |
178 | } // namespace detail |
179 | |
180 | template<class L> using mp_second = typename detail::mp_second_impl<L>::type; |
181 | |
182 | // mp_third<L> |
183 | namespace detail |
184 | { |
185 | |
186 | template<class L> struct mp_third_impl |
187 | { |
188 | // An error "no type named 'type'" here means that the argument to mp_third |
189 | // is either not a list, or has fewer than three elements |
190 | }; |
191 | |
192 | template<template<class...> class L, class T1, class T2, class T3, class... T> struct mp_third_impl<L<T1, T2, T3, T...>> |
193 | { |
194 | using type = T3; |
195 | }; |
196 | |
197 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
198 | |
199 | template<template<auto...> class L, auto A1, auto A2, auto A3, auto... A> struct mp_third_impl<L<A1, A2, A3, A...>> |
200 | { |
201 | using type = mp_value<A3>; |
202 | }; |
203 | |
204 | #endif |
205 | |
206 | } // namespace detail |
207 | |
208 | template<class L> using mp_third = typename detail::mp_third_impl<L>::type; |
209 | |
210 | // mp_push_front<L, T...> |
211 | namespace detail |
212 | { |
213 | |
214 | template<class L, class... T> struct mp_push_front_impl |
215 | { |
216 | // An error "no type named 'type'" here means that the first argument to mp_push_front is not a list |
217 | }; |
218 | |
219 | template<template<class...> class L, class... U, class... T> struct mp_push_front_impl<L<U...>, T...> |
220 | { |
221 | using type = L<T..., U...>; |
222 | }; |
223 | |
224 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
225 | |
226 | template<template<auto...> class L, auto... A, class... T> struct mp_push_front_impl<L<A...>, T...> |
227 | { |
228 | using type = L<T::value..., A...>; |
229 | }; |
230 | |
231 | #endif |
232 | |
233 | } // namespace detail |
234 | |
235 | template<class L, class... T> using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type; |
236 | |
237 | // mp_push_back<L, T...> |
238 | namespace detail |
239 | { |
240 | |
241 | template<class L, class... T> struct mp_push_back_impl |
242 | { |
243 | // An error "no type named 'type'" here means that the first argument to mp_push_back is not a list |
244 | }; |
245 | |
246 | template<template<class...> class L, class... U, class... T> struct mp_push_back_impl<L<U...>, T...> |
247 | { |
248 | using type = L<U..., T...>; |
249 | }; |
250 | |
251 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
252 | |
253 | template<template<auto...> class L, auto... A, class... T> struct mp_push_back_impl<L<A...>, T...> |
254 | { |
255 | using type = L<A..., T::value...>; |
256 | }; |
257 | |
258 | #endif |
259 | |
260 | } // namespace detail |
261 | |
262 | template<class L, class... T> using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type; |
263 | |
264 | // mp_rename<L, B> |
265 | // mp_apply<F, L> |
266 | // mp_apply_q<Q, L> |
267 | // in detail/mp_rename.hpp |
268 | |
269 | // mp_rename_v<L, B> |
270 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
271 | |
272 | namespace detail |
273 | { |
274 | |
275 | template<class L, template<auto...> class B> struct mp_rename_v_impl |
276 | { |
277 | // An error "no type named 'type'" here means that the first argument to mp_rename_v is not a list |
278 | }; |
279 | |
280 | template<template<class...> class L, class... T, template<auto...> class B> struct mp_rename_v_impl<L<T...>, B> |
281 | { |
282 | using type = B<T::value...>; |
283 | }; |
284 | |
285 | template<template<auto...> class L, auto... A, template<auto...> class B> struct mp_rename_v_impl<L<A...>, B> |
286 | { |
287 | using type = B<A...>; |
288 | }; |
289 | |
290 | } // namespace detail |
291 | |
292 | template<class L, template<auto...> class B> using mp_rename_v = typename detail::mp_rename_v_impl<L, B>::type; |
293 | |
294 | #endif |
295 | |
296 | // mp_replace_front<L, T> |
297 | namespace detail |
298 | { |
299 | |
300 | template<class L, class T> struct mp_replace_front_impl |
301 | { |
302 | // An error "no type named 'type'" here means that the first argument to mp_replace_front |
303 | // is either not a list, or is an empty list |
304 | }; |
305 | |
306 | template<template<class...> class L, class U1, class... U, class T> struct mp_replace_front_impl<L<U1, U...>, T> |
307 | { |
308 | using type = L<T, U...>; |
309 | }; |
310 | |
311 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
312 | |
313 | template<template<auto...> class L, auto A1, auto... A, class T> struct mp_replace_front_impl<L<A1, A...>, T> |
314 | { |
315 | using type = L<T::value, A...>; |
316 | }; |
317 | |
318 | #endif |
319 | |
320 | } // namespace detail |
321 | |
322 | template<class L, class T> using mp_replace_front = typename detail::mp_replace_front_impl<L, T>::type; |
323 | |
324 | // mp_replace_first<L, T> |
325 | template<class L, class T> using mp_replace_first = typename detail::mp_replace_front_impl<L, T>::type; |
326 | |
327 | // mp_replace_second<L, T> |
328 | namespace detail |
329 | { |
330 | |
331 | template<class L, class T> struct mp_replace_second_impl |
332 | { |
333 | // An error "no type named 'type'" here means that the first argument to mp_replace_second |
334 | // is either not a list, or has fewer than two elements |
335 | }; |
336 | |
337 | template<template<class...> class L, class U1, class U2, class... U, class T> struct mp_replace_second_impl<L<U1, U2, U...>, T> |
338 | { |
339 | using type = L<U1, T, U...>; |
340 | }; |
341 | |
342 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
343 | |
344 | template<template<auto...> class L, auto A1, auto A2, auto... A, class T> struct mp_replace_second_impl<L<A1, A2, A...>, T> |
345 | { |
346 | using type = L<A1, T::value, A...>; |
347 | }; |
348 | |
349 | #endif |
350 | |
351 | } // namespace detail |
352 | |
353 | template<class L, class T> using mp_replace_second = typename detail::mp_replace_second_impl<L, T>::type; |
354 | |
355 | // mp_replace_third<L, T> |
356 | namespace detail |
357 | { |
358 | |
359 | template<class L, class T> struct mp_replace_third_impl |
360 | { |
361 | // An error "no type named 'type'" here means that the first argument to mp_replace_third |
362 | // is either not a list, or has fewer than three elements |
363 | }; |
364 | |
365 | 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> |
366 | { |
367 | using type = L<U1, U2, T, U...>; |
368 | }; |
369 | |
370 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
371 | |
372 | template<template<auto...> class L, auto A1, auto A2, auto A3, auto... A, class T> struct mp_replace_third_impl<L<A1, A2, A3, A...>, T> |
373 | { |
374 | using type = L<A1, A2, T::value, A...>; |
375 | }; |
376 | |
377 | #endif |
378 | |
379 | } // namespace detail |
380 | |
381 | template<class L, class T> using mp_replace_third = typename detail::mp_replace_third_impl<L, T>::type; |
382 | |
383 | // mp_transform_front<L, F> |
384 | namespace detail |
385 | { |
386 | |
387 | template<class L, template<class...> class F> struct mp_transform_front_impl |
388 | { |
389 | // An error "no type named 'type'" here means that the first argument to mp_transform_front |
390 | // is either not a list, or is an empty list |
391 | }; |
392 | |
393 | template<template<class...> class L, class U1, class... U, template<class...> class F> struct mp_transform_front_impl<L<U1, U...>, F> |
394 | { |
395 | using type = L<F<U1>, U...>; |
396 | }; |
397 | |
398 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
399 | |
400 | template<template<auto...> class L, auto A1, auto... A, template<class...> class F> struct mp_transform_front_impl<L<A1, A...>, F> |
401 | { |
402 | using type = L<F<mp_value<A1>>::value, A...>; |
403 | }; |
404 | |
405 | #endif |
406 | |
407 | } // namespace detail |
408 | |
409 | template<class L, template<class...> class F> using mp_transform_front = typename detail::mp_transform_front_impl<L, F>::type; |
410 | template<class L, class Q> using mp_transform_front_q = mp_transform_front<L, Q::template fn>; |
411 | |
412 | // mp_transform_first<L, F> |
413 | template<class L, template<class...> class F> using mp_transform_first = typename detail::mp_transform_front_impl<L, F>::type; |
414 | template<class L, class Q> using mp_transform_first_q = mp_transform_first<L, Q::template fn>; |
415 | |
416 | // mp_transform_second<L, F> |
417 | namespace detail |
418 | { |
419 | |
420 | template<class L, template<class...> class F> struct mp_transform_second_impl |
421 | { |
422 | // An error "no type named 'type'" here means that the first argument to mp_transform_second |
423 | // is either not a list, or has fewer than two elements |
424 | }; |
425 | |
426 | 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> |
427 | { |
428 | using type = L<U1, F<U2>, U...>; |
429 | }; |
430 | |
431 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
432 | |
433 | template<template<auto...> class L, auto A1, auto A2, auto... A, template<class...> class F> struct mp_transform_second_impl<L<A1, A2, A...>, F> |
434 | { |
435 | using type = L<A1, F<mp_value<A2>>::value, A...>; |
436 | }; |
437 | |
438 | #endif |
439 | |
440 | } // namespace detail |
441 | |
442 | template<class L, template<class...> class F> using mp_transform_second = typename detail::mp_transform_second_impl<L, F>::type; |
443 | template<class L, class Q> using mp_transform_second_q = mp_transform_second<L, Q::template fn>; |
444 | |
445 | // mp_transform_third<L, F> |
446 | namespace detail |
447 | { |
448 | |
449 | template<class L, template<class...> class F> struct mp_transform_third_impl |
450 | { |
451 | // An error "no type named 'type'" here means that the first argument to mp_transform_third |
452 | // is either not a list, or has fewer than three elements |
453 | }; |
454 | |
455 | 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> |
456 | { |
457 | using type = L<U1, U2, F<U3>, U...>; |
458 | }; |
459 | |
460 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
461 | |
462 | template<template<auto...> class L, auto A1, auto A2, auto A3, auto... A, template<class...> class F> struct mp_transform_third_impl<L<A1, A2, A3, A...>, F> |
463 | { |
464 | using type = L<A1, A2, F<mp_value<A3>>::value, A...>; |
465 | }; |
466 | |
467 | #endif |
468 | |
469 | } // namespace detail |
470 | |
471 | template<class L, template<class...> class F> using mp_transform_third = typename detail::mp_transform_third_impl<L, F>::type; |
472 | template<class L, class Q> using mp_transform_third_q = mp_transform_third<L, Q::template fn>; |
473 | |
474 | } // namespace mp11 |
475 | } // namespace boost |
476 | |
477 | #if defined(_MSC_VER) || defined(__GNUC__) |
478 | # pragma pop_macro( "I" ) |
479 | #endif |
480 | |
481 | #endif // #ifndef BOOST_MP11_LIST_HPP_INCLUDED |
482 | |