]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/math/tools/mp.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / math / tools / mp.hpp
CommitLineData
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
18namespace boost { namespace math { namespace tools { namespace meta_programming {
19
20// Types:
21// Typelist
22template<typename... T>
23struct mp_list {};
24
25// Size_t
26template<std::size_t N>
27using mp_size_t = std::integral_constant<std::size_t, N>;
28
29// Boolean
30template<bool B>
31using mp_bool = std::integral_constant<bool, B>;
32
33// Identity
34template<typename T>
35struct mp_identity
36{
37 using type = T;
38};
39
40// Turns struct into quoted metafunction
41template<template<typename...> class F>
42struct mp_quote_trait
43{
44 template<typename... T>
45 using fn = typename F<T...>::type;
46};
47
48namespace detail {
49// Size
50template<typename L>
51struct mp_size_impl {};
52
53template<template<typename...> class L, typename... T> // Template template parameter must use class
54struct mp_size_impl<L<T...>>
55{
56 using type = std::integral_constant<std::size_t, sizeof...(T)>;
57};
58}
59
60template<typename T>
61using mp_size = typename detail::mp_size_impl<T>::type;
62
63namespace detail {
64// Front
65template<typename L>
66struct mp_front_impl {};
67
68template<template<typename...> class L, typename T1, typename... T>
69struct mp_front_impl<L<T1, T...>>
70{
71 using type = T1;
72};
73}
74
75template<typename T>
76using mp_front = typename detail::mp_front_impl<T>::type;
77
78namespace 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
82template<typename L, std::size_t>
83struct mp_at_c {};
84
85template<template<typename...> class L, typename T0, typename... T>
86struct mp_at_c<L<T0, T...>, 0>
87{
88 using type = T0;
89};
90
91template<template<typename...> class L, typename T0, typename T1, typename... T>
92struct mp_at_c<L<T0, T1, T...>, 1>
93{
94 using type = T1;
95};
96
97template<template<typename...> class L, typename T0, typename T1, typename T2, typename... T>
98struct mp_at_c<L<T0, T1, T2, T...>, 2>
99{
100 using type = T2;
101};
102
103template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename... T>
104struct mp_at_c<L<T0, T1, T2, T3, T...>, 3>
105{
106 using type = T3;
107};
108
109template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename... T>
110struct mp_at_c<L<T0, T1, T2, T3, T4, T...>, 4>
111{
112 using type = T4;
113};
114
115template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename... T>
116struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T...>, 5>
117{
118 using type = T5;
119};
120
121template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
122 typename... T>
123struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T...>, 6>
124{
125 using type = T6;
126};
127
128template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
129 typename T7, typename... T>
130struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T...>, 7>
131{
132 using type = T7;
133};
134
135template<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>
137struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T...>, 8>
138{
139 using type = T8;
140};
141
142template<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>
144struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>, 9>
145{
146 using type = T9;
147};
148
149template<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>
151struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, 10>
152{
153 using type = T10;
154};
155
156template<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>
158struct 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
163template<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>
165struct 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
171template<typename L, std::size_t I>
172using mp_at_c = typename detail::mp_at_c<L, I>::type;
173
174template<typename L, typename I>
175using mp_at = typename detail::mp_at_c<L, I::value>::type;
176
177// Back
178template<typename L>
179using mp_back = mp_at_c<L, mp_size<L>::value - 1>;
180
181namespace detail {
182// Push back
183template<typename L, typename... T>
184struct mp_push_back_impl {};
185
186template<template<typename...> class L, typename... U, typename... T>
187struct mp_push_back_impl<L<U...>, T...>
188{
189 using type = L<U..., T...>;
190};
191}
192
193template<typename L, typename... T>
194using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type;
195
196namespace detail {
197// Push front
198template<typename L, typename... T>
199struct mp_push_front_impl {};
200
201template<template<typename...> class L, typename... U, typename... T>
202struct mp_push_front_impl<L<U...>, T...>
203{
204 using type = L<T..., U...>;
205};
206}
207
208template<typename L, typename... T>
209using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;
210
211namespace detail{
212// If
213template<bool C, typename T, typename... E>
214struct mp_if_c_impl{};
215
216template<typename T, typename... E>
217struct mp_if_c_impl<true, T, E...>
218{
219 using type = T;
220};
221
222template<typename T, typename E>
223struct mp_if_c_impl<false, T, E>
224{
225 using type = E;
226};
227}
228
229template<bool C, typename T, typename... E>
230using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
231
232template<typename C, typename T, typename... E>
233using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;
234
235namespace detail {
236// Find if
237template<typename L, template<typename...> class P>
238struct mp_find_if_impl {};
239
240template<template<typename...> class L, template<typename...> class P>
241struct mp_find_if_impl<L<>, P>
242{
243 using type = mp_size_t<0>;
244};
245
246template<typename L, template<typename...> class P>
247struct 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
253template<template<typename...> class L, typename T1, typename... T, template<typename...> class P>
254struct 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
260template<typename L, template<typename...> class P>
261using mp_find_if = typename detail::mp_find_if_impl<L, P>::type;
262
263template<typename L, typename Q>
264using mp_find_if_q = mp_find_if<L, Q::template fn>;
265
266namespace detail {
267// Append
268template<typename... L>
269struct mp_append_impl {};
270
271template<>
272struct mp_append_impl<>
273{
274 using type = mp_list<>;
275};
276
277template<template<typename...> class L, typename... T>
278struct mp_append_impl<L<T...>>
279{
280 using type = L<T...>;
281};
282
283template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2>
284struct mp_append_impl<L1<T1...>, L2<T2...>>
285{
286 using type = L1<T1..., T2...>;
287};
288
289template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
290 template<typename...> class L3, typename... T3>
291struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>>
292{
293 using type = L1<T1..., T2..., T3...>;
294};
295
296template<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>
298struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>>
299{
300 using type = L1<T1..., T2..., T3..., T4...>;
301};
302
303template<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>
306struct 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
312template<typename... L>
313using mp_append = typename detail::mp_append_impl<L...>::type;
314
315namespace detail {
316// Remove if
317template<typename L, template<typename...> class P>
318struct mp_remove_if_impl{};
319
320template<template<typename...> class L, typename... T, template<typename...> class P>
321struct 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
333template<typename L, template<class...> class P>
334using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type;
335
336template<typename L, typename Q>
337using 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)
342template<std::size_t... I>
343using index_sequence = std::index_sequence<I...>;
344
345template<std::size_t N>
346using make_index_sequence = std::make_index_sequence<N>;
347
348template<typename... T>
349using index_sequence_for = std::index_sequence_for<T...>;
350
351#else
352
353template<typename T, T... I>
354struct integer_sequence {};
355
356template<std::size_t... I>
357using index_sequence = integer_sequence<std::size_t, I...>;
358
359namespace detail {
360
361template<bool C, typename T, typename E>
362struct iseq_if_c_impl {};
363
364template<typename T, typename F>
365struct iseq_if_c_impl<true, T, F>
366{
367 using type = T;
368};
369
370template<typename T, typename F>
371struct iseq_if_c_impl<false, T, F>
372{
373 using type = F;
374};
375
376template<bool C, typename T, typename F>
377using iseq_if_c = typename iseq_if_c_impl<C, T, F>::type;
378
379template<typename T>
380struct iseq_identity
381{
382 using type = T;
383};
384
385template<typename T1, typename T2>
386struct append_integer_sequence {};
387
388template<typename T, T... I, T... J>
389struct append_integer_sequence<integer_sequence<T, I...>, integer_sequence<T, J...>>
390{
391 using type = integer_sequence<T, I..., (J + sizeof...(I))...>;
392};
393
394template<typename T, T N>
395struct make_integer_sequence_impl;
396
397template<typename T, T N>
398class make_integer_sequence_impl_
399{
400private:
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
411public:
412 using type = seq4;
413};
414
415template<typename T, T N>
416struct 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
426template<typename T, T N>
427using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type;
428
429template<std::size_t N>
430using make_index_sequence = make_integer_sequence<std::size_t, N>;
431
432template<typename... T>
433using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>;
434
435#endif
436
437}}}} // namespaces
438
439#endif // BOOST_MATH_TOOLS_MP