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