mp.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  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. #ifndef BOOST_MATH_TOOLS_MP
  11. #define BOOST_MATH_TOOLS_MP
  12. #include <type_traits>
  13. #include <cstddef>
  14. namespace boost { namespace math { namespace tools { namespace meta_programming {
  15. // Types:
  16. // Typelist
  17. template<typename... T>
  18. struct mp_list {};
  19. // Size_t
  20. template<std::size_t N>
  21. using mp_size_t = std::integral_constant<std::size_t, N>;
  22. // Boolean
  23. template<bool B>
  24. using mp_bool = std::integral_constant<bool, B>;
  25. // Identity
  26. template<typename T>
  27. struct mp_identity
  28. {
  29. using type = T;
  30. };
  31. // Turns struct into quoted metafunction
  32. template<template<typename...> class F>
  33. struct mp_quote_trait
  34. {
  35. template<typename... T>
  36. using fn = typename F<T...>::type;
  37. };
  38. namespace detail {
  39. // Size
  40. template<typename L>
  41. struct mp_size_impl {};
  42. template<template<typename...> class L, typename... T> // Template template parameter must use class
  43. struct mp_size_impl<L<T...>>
  44. {
  45. using type = std::integral_constant<std::size_t, sizeof...(T)>;
  46. };
  47. }
  48. template<typename T>
  49. using mp_size = typename detail::mp_size_impl<T>::type;
  50. namespace detail {
  51. // Front
  52. template<typename L>
  53. struct mp_front_impl {};
  54. template<template<typename...> class L, typename T1, typename... T>
  55. struct mp_front_impl<L<T1, T...>>
  56. {
  57. using type = T1;
  58. };
  59. }
  60. template<typename T>
  61. using mp_front = typename detail::mp_front_impl<T>::type;
  62. namespace detail {
  63. // At
  64. // TODO - Use tree based lookup for larger typelists
  65. // http://odinthenerd.blogspot.com/2017/04/tree-based-lookup-why-kvasirmpl-is.html
  66. template<typename L, std::size_t>
  67. struct mp_at_c {};
  68. template<template<typename...> class L, typename T0, typename... T>
  69. struct mp_at_c<L<T0, T...>, 0>
  70. {
  71. using type = T0;
  72. };
  73. template<template<typename...> class L, typename T0, typename T1, typename... T>
  74. struct mp_at_c<L<T0, T1, T...>, 1>
  75. {
  76. using type = T1;
  77. };
  78. template<template<typename...> class L, typename T0, typename T1, typename T2, typename... T>
  79. struct mp_at_c<L<T0, T1, T2, T...>, 2>
  80. {
  81. using type = T2;
  82. };
  83. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename... T>
  84. struct mp_at_c<L<T0, T1, T2, T3, T...>, 3>
  85. {
  86. using type = T3;
  87. };
  88. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename... T>
  89. struct mp_at_c<L<T0, T1, T2, T3, T4, T...>, 4>
  90. {
  91. using type = T4;
  92. };
  93. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename... T>
  94. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T...>, 5>
  95. {
  96. using type = T5;
  97. };
  98. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  99. typename... T>
  100. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T...>, 6>
  101. {
  102. using type = T6;
  103. };
  104. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  105. typename T7, typename... T>
  106. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T...>, 7>
  107. {
  108. using type = T7;
  109. };
  110. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  111. typename T7, typename T8, typename... T>
  112. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T...>, 8>
  113. {
  114. using type = T8;
  115. };
  116. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  117. typename T7, typename T8, typename T9, typename... T>
  118. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>, 9>
  119. {
  120. using type = T9;
  121. };
  122. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  123. typename T7, typename T8, typename T9, typename T10, typename... T>
  124. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, 10>
  125. {
  126. using type = T10;
  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 T8, typename T9, typename T10, typename T11, typename... T>
  130. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T...>, 11>
  131. {
  132. using type = T11;
  133. };
  134. template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
  135. typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename... T>
  136. struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T...>, 12>
  137. {
  138. using type = T12;
  139. };
  140. }
  141. template<typename L, std::size_t I>
  142. using mp_at_c = typename detail::mp_at_c<L, I>::type;
  143. template<typename L, typename I>
  144. using mp_at = typename detail::mp_at_c<L, I::value>::type;
  145. // Back
  146. template<typename L>
  147. using mp_back = mp_at_c<L, mp_size<L>::value - 1>;
  148. namespace detail {
  149. // Push back
  150. template<typename L, typename... T>
  151. struct mp_push_back_impl {};
  152. template<template<typename...> class L, typename... U, typename... T>
  153. struct mp_push_back_impl<L<U...>, T...>
  154. {
  155. using type = L<U..., T...>;
  156. };
  157. }
  158. template<typename L, typename... T>
  159. using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type;
  160. namespace detail {
  161. // Push front
  162. template<typename L, typename... T>
  163. struct mp_push_front_impl {};
  164. template<template<typename...> class L, typename... U, typename... T>
  165. struct mp_push_front_impl<L<U...>, T...>
  166. {
  167. using type = L<T..., U...>;
  168. };
  169. }
  170. template<typename L, typename... T>
  171. using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;
  172. namespace detail{
  173. // If
  174. template<bool C, typename T, typename... E>
  175. struct mp_if_c_impl{};
  176. template<typename T, typename... E>
  177. struct mp_if_c_impl<true, T, E...>
  178. {
  179. using type = T;
  180. };
  181. template<typename T, typename E>
  182. struct mp_if_c_impl<false, T, E>
  183. {
  184. using type = E;
  185. };
  186. }
  187. template<bool C, typename T, typename... E>
  188. using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
  189. template<typename C, typename T, typename... E>
  190. using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;
  191. namespace detail {
  192. // Find if
  193. template<typename L, template<typename...> class P>
  194. struct mp_find_if_impl {};
  195. template<template<typename...> class L, template<typename...> class P>
  196. struct mp_find_if_impl<L<>, P>
  197. {
  198. using type = mp_size_t<0>;
  199. };
  200. template<typename L, template<typename...> class P>
  201. struct mp_find_if_impl_2
  202. {
  203. using r = typename mp_find_if_impl<L, P>::type;
  204. using type = mp_size_t<1 + r::value>;
  205. };
  206. template<template<typename...> class L, typename T1, typename... T, template<typename...> class P>
  207. struct mp_find_if_impl<L<T1, T...>, P>
  208. {
  209. using type = typename mp_if<P<T1>, mp_identity<mp_size_t<0>>, mp_find_if_impl_2<mp_list<T...>, P>>::type;
  210. };
  211. }
  212. template<typename L, template<typename...> class P>
  213. using mp_find_if = typename detail::mp_find_if_impl<L, P>::type;
  214. template<typename L, typename Q>
  215. using mp_find_if_q = mp_find_if<L, Q::template fn>;
  216. namespace detail {
  217. // Append
  218. template<typename... L>
  219. struct mp_append_impl {};
  220. template<>
  221. struct mp_append_impl<>
  222. {
  223. using type = mp_list<>;
  224. };
  225. template<template<typename...> class L, typename... T>
  226. struct mp_append_impl<L<T...>>
  227. {
  228. using type = L<T...>;
  229. };
  230. template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2>
  231. struct mp_append_impl<L1<T1...>, L2<T2...>>
  232. {
  233. using type = L1<T1..., T2...>;
  234. };
  235. template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
  236. template<typename...> class L3, typename... T3>
  237. struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>>
  238. {
  239. using type = L1<T1..., T2..., T3...>;
  240. };
  241. template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
  242. template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4>
  243. struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>>
  244. {
  245. using type = L1<T1..., T2..., T3..., T4...>;
  246. };
  247. template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
  248. template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4,
  249. template<typename...> class L5, typename... T5, typename... Lr>
  250. struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L5<T5...>, Lr...>
  251. {
  252. using type = typename mp_append_impl<L1<T1..., T2..., T3..., T4..., T5...>, Lr...>::type;
  253. };
  254. }
  255. template<typename... L>
  256. using mp_append = typename detail::mp_append_impl<L...>::type;
  257. namespace detail {
  258. // Remove if
  259. template<typename L, template<typename...> class P>
  260. struct mp_remove_if_impl{};
  261. template<template<typename...> class L, typename... T, template<typename...> class P>
  262. struct mp_remove_if_impl<L<T...>, P>
  263. {
  264. template<typename U>
  265. struct _f
  266. {
  267. using type = mp_if<P<U>, mp_list<>, mp_list<U>>;
  268. };
  269. using type = mp_append<L<>, typename _f<T>::type...>;
  270. };
  271. }
  272. template<typename L, template<class...> class P>
  273. using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type;
  274. template<typename L, typename Q>
  275. using mp_remove_if_q = mp_remove_if<L, Q::template fn>;
  276. // Index sequence
  277. // Use C++14 index sequence if available
  278. #if defined(__cpp_lib_integer_sequence) && (__cpp_lib_integer_sequence >= 201304)
  279. #include <utility>
  280. template<std::size_t... I>
  281. using index_sequence = std::index_sequence<I...>;
  282. template<std::size_t N>
  283. using make_index_sequence = std::make_index_sequence<N>;
  284. template<typename... T>
  285. using index_sequence_for = std::index_sequence_for<T...>;
  286. #else
  287. template<typename T, T... I>
  288. struct integer_sequence {};
  289. template<std::size_t... I>
  290. using index_sequence = integer_sequence<std::size_t, I...>;
  291. namespace detail {
  292. template<bool C, typename T, typename E>
  293. struct iseq_if_c_impl {};
  294. template<typename T, typename F>
  295. struct iseq_if_c_impl<true, T, F>
  296. {
  297. using type = T;
  298. };
  299. template<typename T, typename F>
  300. struct iseq_if_c_impl<false, T, F>
  301. {
  302. using type = F;
  303. };
  304. template<bool C, typename T, typename F>
  305. using iseq_if_c = typename iseq_if_c_impl<C, T, F>::type;
  306. template<typename T>
  307. struct iseq_identity
  308. {
  309. using type = T;
  310. };
  311. template<typename T1, typename T2>
  312. struct append_integer_sequence {};
  313. template<typename T, T... I, T... J>
  314. struct append_integer_sequence<integer_sequence<T, I...>, integer_sequence<T, J...>>
  315. {
  316. using type = integer_sequence<T, I..., (J + sizeof...(I))...>;
  317. };
  318. template<typename T, T N>
  319. struct make_integer_sequence_impl;
  320. template<typename T, T N>
  321. class make_integer_sequence_impl_
  322. {
  323. private:
  324. static_assert(N >= 0, "N must not be negative");
  325. static constexpr T M = N / 2;
  326. static constexpr T R = N % 2;
  327. using seq1 = typename make_integer_sequence_impl<T, M>::type;
  328. using seq2 = typename append_integer_sequence<seq1, seq1>::type;
  329. using seq3 = typename make_integer_sequence_impl<T, R>::type;
  330. using seq4 = typename append_integer_sequence<seq2, seq3>::type;
  331. public:
  332. using type = seq4;
  333. };
  334. template<typename T, T N>
  335. struct make_integer_sequence_impl
  336. {
  337. using type = typename iseq_if_c<N == 0,
  338. iseq_identity<integer_sequence<T>>,
  339. iseq_if_c<N == 1, iseq_identity<integer_sequence<T, 0>>,
  340. make_integer_sequence_impl_<T, N>>>::type;
  341. };
  342. } // namespace detail
  343. template<typename T, T N>
  344. using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type;
  345. template<std::size_t... I>
  346. using index_sequence = integer_sequence<std::size_t, I...>;
  347. template<std::size_t N>
  348. using make_index_sequence = make_integer_sequence<std::size_t, N>;
  349. template<typename... T>
  350. using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>;
  351. #endif
  352. }}}} // namespaces
  353. #endif // BOOST_MATH_TOOLS_MP