You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

265 lines
11 KiB

  1. #pragma once
  2. #include <utility>
  3. #include <cpputils/mp/misc/when.h>
  4. namespace utl {
  5. namespace mp {
  6. namespace intern {
  7. namespace __impl
  8. {
  9. template <unsigned int n, typename = when<true>>
  10. struct fold_left_impl;
  11. template<>
  12. struct fold_left_impl<1>
  13. {
  14. template<typename F, typename X1>
  15. static constexpr X1 apply(F&&, X1&& x1)
  16. { return std::forward<X1>(x1); }
  17. };
  18. template<>
  19. struct fold_left_impl<2>
  20. {
  21. template<typename F, typename X1, typename X2>
  22. static constexpr auto apply(F&& f, X1&& x1, X2&& x2)
  23. {
  24. return f(
  25. std::forward<X1>(x1),
  26. std::forward<X2>(x2));
  27. }
  28. };
  29. template<>
  30. struct fold_left_impl<3>
  31. {
  32. template<typename F, typename X1, typename X2, typename X3>
  33. static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3)
  34. {
  35. return f(f(
  36. std::forward<X1>(x1),
  37. std::forward<X2>(x2)),
  38. std::forward<X3>(x3));
  39. }
  40. };
  41. template<>
  42. struct fold_left_impl<4>
  43. {
  44. template<typename F, typename X1, typename X2, typename X3, typename X4>
  45. static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4)
  46. {
  47. return f(f(f(
  48. std::forward<X1>(x1),
  49. std::forward<X2>(x2)),
  50. std::forward<X3>(x3)),
  51. std::forward<X4>(x4));
  52. }
  53. };
  54. template<>
  55. struct fold_left_impl<5>
  56. {
  57. template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5>
  58. static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5)
  59. {
  60. return f(f(f(f(
  61. std::forward<X1>(x1),
  62. std::forward<X2>(x2)),
  63. std::forward<X3>(x3)),
  64. std::forward<X4>(x4)),
  65. std::forward<X5>(x5));
  66. }
  67. };
  68. template<>
  69. struct fold_left_impl<6>
  70. {
  71. template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6>
  72. static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6)
  73. {
  74. return f(f(f(f(f(
  75. std::forward<X1>(x1),
  76. std::forward<X2>(x2)),
  77. std::forward<X3>(x3)),
  78. std::forward<X4>(x4)),
  79. std::forward<X5>(x5)),
  80. std::forward<X6>(x6));
  81. }
  82. };
  83. template<>
  84. struct fold_left_impl<7>
  85. {
  86. template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7>
  87. static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7)
  88. {
  89. return f(f(f(f(f(f(
  90. std::forward<X1>(x1),
  91. std::forward<X2>(x2)),
  92. std::forward<X3>(x3)),
  93. std::forward<X4>(x4)),
  94. std::forward<X5>(x5)),
  95. std::forward<X6>(x6)),
  96. std::forward<X7>(x7));
  97. }
  98. };
  99. template<>
  100. struct fold_left_impl<8>
  101. {
  102. template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8>
  103. static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8)
  104. {
  105. return f(f(f(f(f(f(f(
  106. std::forward<X1>(x1),
  107. std::forward<X2>(x2)),
  108. std::forward<X3>(x3)),
  109. std::forward<X4>(x4)),
  110. std::forward<X5>(x5)),
  111. std::forward<X6>(x6)),
  112. std::forward<X7>(x7)),
  113. std::forward<X8>(x8));
  114. }
  115. };
  116. template<unsigned int n>
  117. struct fold_left_impl<n, when<(n >= 9) && (n < 18)>>
  118. {
  119. template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename X9, typename... Xn>
  120. static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, X9&& x9, Xn&&... xn)
  121. {
  122. return fold_left_impl<sizeof...(xn) + 1>::apply(
  123. f,
  124. f(f(f(f(f(f(f(f(
  125. std::forward<X1>(x1),
  126. std::forward<X2>(x2)),
  127. std::forward<X3>(x3)),
  128. std::forward<X4>(x4)),
  129. std::forward<X5>(x5)),
  130. std::forward<X6>(x6)),
  131. std::forward<X7>(x7)),
  132. std::forward<X8>(x8)),
  133. std::forward<X9>(x9)),
  134. std::forward<Xn>(xn)...
  135. );
  136. }
  137. };
  138. template<unsigned int n>
  139. struct fold_left_impl<n, when<(n >= 18) && (n < 36)>>
  140. {
  141. template<
  142. typename F,
  143. typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename X9,
  144. typename X10, typename X11, typename X12, typename X13, typename X14, typename X15, typename X16, typename X17, typename X18,
  145. typename... Xn>
  146. static constexpr auto apply(
  147. F&& f,
  148. X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, X9&& x9,
  149. X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14, X15&& x15, X16&& x16, X17&& x17, X18&& x18,
  150. Xn&&... xn)
  151. {
  152. return fold_left_impl<sizeof...(xn) + 1>::apply(
  153. f,
  154. f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(
  155. std::forward<X1> (x1),
  156. std::forward<X2> (x2)),
  157. std::forward<X3> (x3)),
  158. std::forward<X4> (x4)),
  159. std::forward<X5> (x5)),
  160. std::forward<X6> (x6)),
  161. std::forward<X7> (x7)),
  162. std::forward<X8> (x8)),
  163. std::forward<X9> (x9)),
  164. std::forward<X10>(x10)),
  165. std::forward<X11>(x11)),
  166. std::forward<X12>(x12)),
  167. std::forward<X13>(x13)),
  168. std::forward<X14>(x14)),
  169. std::forward<X15>(x15)),
  170. std::forward<X16>(x16)),
  171. std::forward<X17>(x17)),
  172. std::forward<X18>(x18)),
  173. std::forward<Xn>(xn)...
  174. );
  175. }
  176. };
  177. template<unsigned int n>
  178. struct fold_left_impl<n, when<(n >= 36)>>
  179. {
  180. template<
  181. typename F,
  182. typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename X9,
  183. typename X10, typename X11, typename X12, typename X13, typename X14, typename X15, typename X16, typename X17, typename X18,
  184. typename X19, typename X20, typename X21, typename X22, typename X23, typename X24, typename X25, typename X26, typename X27,
  185. typename X28, typename X29, typename X30, typename X31, typename X32, typename X33, typename X34, typename X35, typename X36,
  186. typename... Xn>
  187. static constexpr auto apply(
  188. F&& f,
  189. X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, X9&& x9,
  190. X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14, X15&& x15, X16&& x16, X17&& x17, X18&& x18,
  191. X19&& x19, X20&& x20, X21&& x21, X22&& x22, X23&& x23, X24&& x24, X25&& x25, X26&& x26, X27&& x27,
  192. X28&& x28, X29&& x29, X30&& x30, X31&& x31, X32&& x32, X33&& x33, X34&& x34, X35&& x35, X36&& x36,
  193. Xn&&... xn)
  194. {
  195. return fold_left_impl<sizeof...(xn) + 1>::apply(
  196. f,
  197. f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(
  198. std::forward<X1> (x1),
  199. std::forward<X2> (x2)),
  200. std::forward<X3> (x3)),
  201. std::forward<X4> (x4)),
  202. std::forward<X5> (x5)),
  203. std::forward<X6> (x6)),
  204. std::forward<X7> (x7)),
  205. std::forward<X8> (x8)),
  206. std::forward<X9> (x9)),
  207. std::forward<X10>(x10)),
  208. std::forward<X11>(x11)),
  209. std::forward<X12>(x12)),
  210. std::forward<X13>(x13)),
  211. std::forward<X14>(x14)),
  212. std::forward<X15>(x15)),
  213. std::forward<X16>(x16)),
  214. std::forward<X17>(x17)),
  215. std::forward<X18>(x18)),
  216. std::forward<X19>(x19)),
  217. std::forward<X20>(x20)),
  218. std::forward<X21>(x21)),
  219. std::forward<X22>(x22)),
  220. std::forward<X23>(x23)),
  221. std::forward<X24>(x24)),
  222. std::forward<X25>(x25)),
  223. std::forward<X26>(x26)),
  224. std::forward<X27>(x27)),
  225. std::forward<X28>(x28)),
  226. std::forward<X29>(x29)),
  227. std::forward<X30>(x30)),
  228. std::forward<X31>(x31)),
  229. std::forward<X32>(x32)),
  230. std::forward<X33>(x33)),
  231. std::forward<X34>(x34)),
  232. std::forward<X35>(x35)),
  233. std::forward<X36>(x36)),
  234. std::forward<Xn>(xn)...
  235. );
  236. }
  237. };
  238. struct fold_left_t
  239. {
  240. template<typename F, typename X1, typename... Xn>
  241. constexpr auto operator()(F&& f, X1&& x1, Xn&&... xn) const
  242. { return fold_left_impl<sizeof...(xn) + 1>::apply(std::forward<F>(f), std::forward<X1>(x1), std::forward<Xn>(xn)...); }
  243. };
  244. }
  245. constexpr __impl::fold_left_t fold_left { };
  246. }
  247. }
  248. }