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
27namespace boost
28{
29namespace mp11
30{
31
32// mp_list<T...>
33// in detail/mp_list.hpp
34
35// mp_list_c<T, I...>
36template<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>
48namespace detail
49{
50
51template<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
56template<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
63template<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
72template<class L> using mp_size = typename detail::mp_size_impl<L>::type;
73
74// mp_empty<L>
75template<class L> using mp_empty = mp_bool< mp_size<L>::value == 0 >;
76
77// mp_assign<L1, L2>
78namespace detail
79{
80
81template<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
86template<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
93template<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
98template<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
103template<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
112template<class L1, class L2> using mp_assign = typename detail::mp_assign_impl<L1, L2>::type;
113
114// mp_clear<L>
115template<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>
121namespace detail
122{
123
124template<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
130template<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
137template<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
146template<class L> using mp_pop_front = typename detail::mp_pop_front_impl<L>::type;
147
148// mp_first<L>
149template<class L> using mp_first = mp_front<L>;
150
151// mp_rest<L>
152template<class L> using mp_rest = mp_pop_front<L>;
153
154// mp_second<L>
155namespace detail
156{
157
158template<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
164template<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
171template<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
180template<class L> using mp_second = typename detail::mp_second_impl<L>::type;
181
182// mp_third<L>
183namespace detail
184{
185
186template<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
192template<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
199template<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
208template<class L> using mp_third = typename detail::mp_third_impl<L>::type;
209
210// mp_push_front<L, T...>
211namespace detail
212{
213
214template<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
219template<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
226template<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
235template<class L, class... T> using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;
236
237// mp_push_back<L, T...>
238namespace detail
239{
240
241template<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
246template<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
253template<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
262template<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
272namespace detail
273{
274
275template<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
280template<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
285template<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
292template<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>
297namespace detail
298{
299
300template<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
306template<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
313template<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
322template<class L, class T> using mp_replace_front = typename detail::mp_replace_front_impl<L, T>::type;
323
324// mp_replace_first<L, T>
325template<class L, class T> using mp_replace_first = typename detail::mp_replace_front_impl<L, T>::type;
326
327// mp_replace_second<L, T>
328namespace detail
329{
330
331template<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
337template<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
344template<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
353template<class L, class T> using mp_replace_second = typename detail::mp_replace_second_impl<L, T>::type;
354
355// mp_replace_third<L, T>
356namespace detail
357{
358
359template<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
365template<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
372template<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
381template<class L, class T> using mp_replace_third = typename detail::mp_replace_third_impl<L, T>::type;
382
383// mp_transform_front<L, F>
384namespace detail
385{
386
387template<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
393template<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
400template<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
409template<class L, template<class...> class F> using mp_transform_front = typename detail::mp_transform_front_impl<L, F>::type;
410template<class L, class Q> using mp_transform_front_q = mp_transform_front<L, Q::template fn>;
411
412// mp_transform_first<L, F>
413template<class L, template<class...> class F> using mp_transform_first = typename detail::mp_transform_front_impl<L, F>::type;
414template<class L, class Q> using mp_transform_first_q = mp_transform_first<L, Q::template fn>;
415
416// mp_transform_second<L, F>
417namespace detail
418{
419
420template<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
426template<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
433template<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
442template<class L, template<class...> class F> using mp_transform_second = typename detail::mp_transform_second_impl<L, F>::type;
443template<class L, class Q> using mp_transform_second_q = mp_transform_second<L, Q::template fn>;
444
445// mp_transform_third<L, F>
446namespace detail
447{
448
449template<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
455template<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
462template<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
471template<class L, template<class...> class F> using mp_transform_third = typename detail::mp_transform_third_impl<L, F>::type;
472template<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

source code of boost/libs/mp11/include/boost/mp11/list.hpp