]>
Commit | Line | Data |
---|---|---|
1e59de90 TL |
1 | // Copyright Peter Dimov 2015-2021. |
2 | // Copyright Matt Borland 2021. | |
3 | // Use, modification and distribution are subject to the | |
4 | // Boost Software License, Version 1.0. (See accompanying file | |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | // Template metaprogramming classes and functions to replace MPL | |
8 | // Source: http://www.pdimov.com/cpp2/simple_cxx11_metaprogramming.html | |
9 | // Source: https://github.com/boostorg/mp11/ | |
10 | ||
11 | #ifndef BOOST_MATH_TOOLS_MP | |
12 | #define BOOST_MATH_TOOLS_MP | |
13 | ||
14 | #include <type_traits> | |
15 | #include <cstddef> | |
16 | #include <utility> | |
17 | ||
18 | namespace boost { namespace math { namespace tools { namespace meta_programming { | |
19 | ||
20 | // Types: | |
21 | // Typelist | |
22 | template<typename... T> | |
23 | struct mp_list {}; | |
24 | ||
25 | // Size_t | |
26 | template<std::size_t N> | |
27 | using mp_size_t = std::integral_constant<std::size_t, N>; | |
28 | ||
29 | // Boolean | |
30 | template<bool B> | |
31 | using mp_bool = std::integral_constant<bool, B>; | |
32 | ||
33 | // Identity | |
34 | template<typename T> | |
35 | struct mp_identity | |
36 | { | |
37 | using type = T; | |
38 | }; | |
39 | ||
40 | // Turns struct into quoted metafunction | |
41 | template<template<typename...> class F> | |
42 | struct mp_quote_trait | |
43 | { | |
44 | template<typename... T> | |
45 | using fn = typename F<T...>::type; | |
46 | }; | |
47 | ||
48 | namespace detail { | |
49 | // Size | |
50 | template<typename L> | |
51 | struct mp_size_impl {}; | |
52 | ||
53 | template<template<typename...> class L, typename... T> // Template template parameter must use class | |
54 | struct mp_size_impl<L<T...>> | |
55 | { | |
56 | using type = std::integral_constant<std::size_t, sizeof...(T)>; | |
57 | }; | |
58 | } | |
59 | ||
60 | template<typename T> | |
61 | using mp_size = typename detail::mp_size_impl<T>::type; | |
62 | ||
63 | namespace detail { | |
64 | // Front | |
65 | template<typename L> | |
66 | struct mp_front_impl {}; | |
67 | ||
68 | template<template<typename...> class L, typename T1, typename... T> | |
69 | struct mp_front_impl<L<T1, T...>> | |
70 | { | |
71 | using type = T1; | |
72 | }; | |
73 | } | |
74 | ||
75 | template<typename T> | |
76 | using mp_front = typename detail::mp_front_impl<T>::type; | |
77 | ||
78 | namespace detail { | |
79 | // At | |
80 | // TODO - Use tree based lookup for larger typelists | |
81 | // http://odinthenerd.blogspot.com/2017/04/tree-based-lookup-why-kvasirmpl-is.html | |
82 | template<typename L, std::size_t> | |
83 | struct mp_at_c {}; | |
84 | ||
85 | template<template<typename...> class L, typename T0, typename... T> | |
86 | struct mp_at_c<L<T0, T...>, 0> | |
87 | { | |
88 | using type = T0; | |
89 | }; | |
90 | ||
91 | template<template<typename...> class L, typename T0, typename T1, typename... T> | |
92 | struct mp_at_c<L<T0, T1, T...>, 1> | |
93 | { | |
94 | using type = T1; | |
95 | }; | |
96 | ||
97 | template<template<typename...> class L, typename T0, typename T1, typename T2, typename... T> | |
98 | struct mp_at_c<L<T0, T1, T2, T...>, 2> | |
99 | { | |
100 | using type = T2; | |
101 | }; | |
102 | ||
103 | template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename... T> | |
104 | struct mp_at_c<L<T0, T1, T2, T3, T...>, 3> | |
105 | { | |
106 | using type = T3; | |
107 | }; | |
108 | ||
109 | template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename... T> | |
110 | struct mp_at_c<L<T0, T1, T2, T3, T4, T...>, 4> | |
111 | { | |
112 | using type = T4; | |
113 | }; | |
114 | ||
115 | template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename... T> | |
116 | struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T...>, 5> | |
117 | { | |
118 | using type = T5; | |
119 | }; | |
120 | ||
121 | template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, | |
122 | typename... T> | |
123 | struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T...>, 6> | |
124 | { | |
125 | using type = T6; | |
126 | }; | |
127 | ||
128 | template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, | |
129 | typename T7, typename... T> | |
130 | struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T...>, 7> | |
131 | { | |
132 | using type = T7; | |
133 | }; | |
134 | ||
135 | template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, | |
136 | typename T7, typename T8, typename... T> | |
137 | struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T...>, 8> | |
138 | { | |
139 | using type = T8; | |
140 | }; | |
141 | ||
142 | template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, | |
143 | typename T7, typename T8, typename T9, typename... T> | |
144 | struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>, 9> | |
145 | { | |
146 | using type = T9; | |
147 | }; | |
148 | ||
149 | template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, | |
150 | typename T7, typename T8, typename T9, typename T10, typename... T> | |
151 | struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, 10> | |
152 | { | |
153 | using type = T10; | |
154 | }; | |
155 | ||
156 | template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, | |
157 | typename T7, typename T8, typename T9, typename T10, typename T11, typename... T> | |
158 | struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T...>, 11> | |
159 | { | |
160 | using type = T11; | |
161 | }; | |
162 | ||
163 | template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, | |
164 | typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename... T> | |
165 | struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T...>, 12> | |
166 | { | |
167 | using type = T12; | |
168 | }; | |
169 | } | |
170 | ||
171 | template<typename L, std::size_t I> | |
172 | using mp_at_c = typename detail::mp_at_c<L, I>::type; | |
173 | ||
174 | template<typename L, typename I> | |
175 | using mp_at = typename detail::mp_at_c<L, I::value>::type; | |
176 | ||
177 | // Back | |
178 | template<typename L> | |
179 | using mp_back = mp_at_c<L, mp_size<L>::value - 1>; | |
180 | ||
181 | namespace detail { | |
182 | // Push back | |
183 | template<typename L, typename... T> | |
184 | struct mp_push_back_impl {}; | |
185 | ||
186 | template<template<typename...> class L, typename... U, typename... T> | |
187 | struct mp_push_back_impl<L<U...>, T...> | |
188 | { | |
189 | using type = L<U..., T...>; | |
190 | }; | |
191 | } | |
192 | ||
193 | template<typename L, typename... T> | |
194 | using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type; | |
195 | ||
196 | namespace detail { | |
197 | // Push front | |
198 | template<typename L, typename... T> | |
199 | struct mp_push_front_impl {}; | |
200 | ||
201 | template<template<typename...> class L, typename... U, typename... T> | |
202 | struct mp_push_front_impl<L<U...>, T...> | |
203 | { | |
204 | using type = L<T..., U...>; | |
205 | }; | |
206 | } | |
207 | ||
208 | template<typename L, typename... T> | |
209 | using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type; | |
210 | ||
211 | namespace detail{ | |
212 | // If | |
213 | template<bool C, typename T, typename... E> | |
214 | struct mp_if_c_impl{}; | |
215 | ||
216 | template<typename T, typename... E> | |
217 | struct mp_if_c_impl<true, T, E...> | |
218 | { | |
219 | using type = T; | |
220 | }; | |
221 | ||
222 | template<typename T, typename E> | |
223 | struct mp_if_c_impl<false, T, E> | |
224 | { | |
225 | using type = E; | |
226 | }; | |
227 | } | |
228 | ||
229 | template<bool C, typename T, typename... E> | |
230 | using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type; | |
231 | ||
232 | template<typename C, typename T, typename... E> | |
233 | using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type; | |
234 | ||
235 | namespace detail { | |
236 | // Find if | |
237 | template<typename L, template<typename...> class P> | |
238 | struct mp_find_if_impl {}; | |
239 | ||
240 | template<template<typename...> class L, template<typename...> class P> | |
241 | struct mp_find_if_impl<L<>, P> | |
242 | { | |
243 | using type = mp_size_t<0>; | |
244 | }; | |
245 | ||
246 | template<typename L, template<typename...> class P> | |
247 | struct mp_find_if_impl_2 | |
248 | { | |
249 | using r = typename mp_find_if_impl<L, P>::type; | |
250 | using type = mp_size_t<1 + r::value>; | |
251 | }; | |
252 | ||
253 | template<template<typename...> class L, typename T1, typename... T, template<typename...> class P> | |
254 | struct mp_find_if_impl<L<T1, T...>, P> | |
255 | { | |
256 | using type = typename mp_if<P<T1>, mp_identity<mp_size_t<0>>, mp_find_if_impl_2<mp_list<T...>, P>>::type; | |
257 | }; | |
258 | } | |
259 | ||
260 | template<typename L, template<typename...> class P> | |
261 | using mp_find_if = typename detail::mp_find_if_impl<L, P>::type; | |
262 | ||
263 | template<typename L, typename Q> | |
264 | using mp_find_if_q = mp_find_if<L, Q::template fn>; | |
265 | ||
266 | namespace detail { | |
267 | // Append | |
268 | template<typename... L> | |
269 | struct mp_append_impl {}; | |
270 | ||
271 | template<> | |
272 | struct mp_append_impl<> | |
273 | { | |
274 | using type = mp_list<>; | |
275 | }; | |
276 | ||
277 | template<template<typename...> class L, typename... T> | |
278 | struct mp_append_impl<L<T...>> | |
279 | { | |
280 | using type = L<T...>; | |
281 | }; | |
282 | ||
283 | template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2> | |
284 | struct mp_append_impl<L1<T1...>, L2<T2...>> | |
285 | { | |
286 | using type = L1<T1..., T2...>; | |
287 | }; | |
288 | ||
289 | template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2, | |
290 | template<typename...> class L3, typename... T3> | |
291 | struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>> | |
292 | { | |
293 | using type = L1<T1..., T2..., T3...>; | |
294 | }; | |
295 | ||
296 | template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2, | |
297 | template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4> | |
298 | struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>> | |
299 | { | |
300 | using type = L1<T1..., T2..., T3..., T4...>; | |
301 | }; | |
302 | ||
303 | template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2, | |
304 | template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4, | |
305 | template<typename...> class L5, typename... T5, typename... Lr> | |
306 | struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L5<T5...>, Lr...> | |
307 | { | |
308 | using type = typename mp_append_impl<L1<T1..., T2..., T3..., T4..., T5...>, Lr...>::type; | |
309 | }; | |
310 | } | |
311 | ||
312 | template<typename... L> | |
313 | using mp_append = typename detail::mp_append_impl<L...>::type; | |
314 | ||
315 | namespace detail { | |
316 | // Remove if | |
317 | template<typename L, template<typename...> class P> | |
318 | struct mp_remove_if_impl{}; | |
319 | ||
320 | template<template<typename...> class L, typename... T, template<typename...> class P> | |
321 | struct mp_remove_if_impl<L<T...>, P> | |
322 | { | |
323 | template<typename U> | |
324 | struct _f | |
325 | { | |
326 | using type = mp_if<P<U>, mp_list<>, mp_list<U>>; | |
327 | }; | |
328 | ||
329 | using type = mp_append<L<>, typename _f<T>::type...>; | |
330 | }; | |
331 | } | |
332 | ||
333 | template<typename L, template<class...> class P> | |
334 | using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type; | |
335 | ||
336 | template<typename L, typename Q> | |
337 | using mp_remove_if_q = mp_remove_if<L, Q::template fn>; | |
338 | ||
339 | // Index sequence | |
340 | // Use C++14 index sequence if available | |
341 | #if defined(__cpp_lib_integer_sequence) && (__cpp_lib_integer_sequence >= 201304) | |
342 | template<std::size_t... I> | |
343 | using index_sequence = std::index_sequence<I...>; | |
344 | ||
345 | template<std::size_t N> | |
346 | using make_index_sequence = std::make_index_sequence<N>; | |
347 | ||
348 | template<typename... T> | |
349 | using index_sequence_for = std::index_sequence_for<T...>; | |
350 | ||
351 | #else | |
352 | ||
353 | template<typename T, T... I> | |
354 | struct integer_sequence {}; | |
355 | ||
356 | template<std::size_t... I> | |
357 | using index_sequence = integer_sequence<std::size_t, I...>; | |
358 | ||
359 | namespace detail { | |
360 | ||
361 | template<bool C, typename T, typename E> | |
362 | struct iseq_if_c_impl {}; | |
363 | ||
364 | template<typename T, typename F> | |
365 | struct iseq_if_c_impl<true, T, F> | |
366 | { | |
367 | using type = T; | |
368 | }; | |
369 | ||
370 | template<typename T, typename F> | |
371 | struct iseq_if_c_impl<false, T, F> | |
372 | { | |
373 | using type = F; | |
374 | }; | |
375 | ||
376 | template<bool C, typename T, typename F> | |
377 | using iseq_if_c = typename iseq_if_c_impl<C, T, F>::type; | |
378 | ||
379 | template<typename T> | |
380 | struct iseq_identity | |
381 | { | |
382 | using type = T; | |
383 | }; | |
384 | ||
385 | template<typename T1, typename T2> | |
386 | struct append_integer_sequence {}; | |
387 | ||
388 | template<typename T, T... I, T... J> | |
389 | struct append_integer_sequence<integer_sequence<T, I...>, integer_sequence<T, J...>> | |
390 | { | |
391 | using type = integer_sequence<T, I..., (J + sizeof...(I))...>; | |
392 | }; | |
393 | ||
394 | template<typename T, T N> | |
395 | struct make_integer_sequence_impl; | |
396 | ||
397 | template<typename T, T N> | |
398 | class make_integer_sequence_impl_ | |
399 | { | |
400 | private: | |
401 | static_assert(N >= 0, "N must not be negative"); | |
402 | ||
403 | static constexpr T M = N / 2; | |
404 | static constexpr T R = N % 2; | |
405 | ||
406 | using seq1 = typename make_integer_sequence_impl<T, M>::type; | |
407 | using seq2 = typename append_integer_sequence<seq1, seq1>::type; | |
408 | using seq3 = typename make_integer_sequence_impl<T, R>::type; | |
409 | using seq4 = typename append_integer_sequence<seq2, seq3>::type; | |
410 | ||
411 | public: | |
412 | using type = seq4; | |
413 | }; | |
414 | ||
415 | template<typename T, T N> | |
416 | struct make_integer_sequence_impl | |
417 | { | |
418 | using type = typename iseq_if_c<N == 0, | |
419 | iseq_identity<integer_sequence<T>>, | |
420 | iseq_if_c<N == 1, iseq_identity<integer_sequence<T, 0>>, | |
421 | make_integer_sequence_impl_<T, N>>>::type; | |
422 | }; | |
423 | ||
424 | } // namespace detail | |
425 | ||
426 | template<typename T, T N> | |
427 | using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type; | |
428 | ||
429 | template<std::size_t N> | |
430 | using make_index_sequence = make_integer_sequence<std::size_t, N>; | |
431 | ||
432 | template<typename... T> | |
433 | using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>; | |
434 | ||
435 | #endif | |
436 | ||
437 | }}}} // namespaces | |
438 | ||
439 | #endif // BOOST_MATH_TOOLS_MP |