mp_fold.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #ifndef BHO_MP11_DETAIL_MP_FOLD_HPP_INCLUDED
  2. #define BHO_MP11_DETAIL_MP_FOLD_HPP_INCLUDED
  3. // Copyright 2015-2017 Peter Dimov.
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. //
  7. // See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt
  9. #include <asio2/bho/mp11/detail/config.hpp>
  10. #include <asio2/bho/mp11/detail/mp_defer.hpp>
  11. namespace bho
  12. {
  13. namespace mp11
  14. {
  15. // mp_fold<L, V, F>
  16. namespace detail
  17. {
  18. template<class L, class V, template<class...> class F> struct mp_fold_impl
  19. {
  20. // An error "no type named 'type'" here means that the first argument to mp_fold is not a list
  21. };
  22. #if BHO_MP11_WORKAROUND( BHO_MP11_MSVC, <= 1800 )
  23. template<template<class...> class L, class... T, class V, template<class...> class F> struct mp_fold_impl<L<T...>, V, F>
  24. {
  25. static_assert( sizeof...(T) == 0, "T... must be empty" );
  26. using type = V;
  27. };
  28. #else
  29. template<template<class...> class L, class V, template<class...> class F> struct mp_fold_impl<L<>, V, F>
  30. {
  31. using type = V;
  32. };
  33. #endif
  34. //
  35. template<class V, template<class...> class F> struct mp_fold_Q1
  36. {
  37. template<class T1>
  38. using fn = F<V, T1>;
  39. };
  40. template<class V, template<class...> class F> struct mp_fold_Q2
  41. {
  42. template<class T1, class T2>
  43. using fn = F<F<V, T1>, T2>;
  44. };
  45. template<class V, template<class...> class F> struct mp_fold_Q3
  46. {
  47. template<class T1, class T2, class T3>
  48. using fn = F<F<F<V, T1>, T2>, T3>;
  49. };
  50. template<class V, template<class...> class F> struct mp_fold_Q4
  51. {
  52. template<class T1, class T2, class T3, class T4>
  53. using fn = F<F<F<F<V, T1>, T2>, T3>, T4>;
  54. };
  55. template<class V, template<class...> class F> struct mp_fold_Q5
  56. {
  57. template<class T1, class T2, class T3, class T4, class T5>
  58. using fn = F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>;
  59. };
  60. template<class V, template<class...> class F> struct mp_fold_Q6
  61. {
  62. template<class T1, class T2, class T3, class T4, class T5, class T6>
  63. using fn = F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>;
  64. };
  65. template<class V, template<class...> class F> struct mp_fold_Q7
  66. {
  67. template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
  68. using fn = F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>;
  69. };
  70. template<class V, template<class...> class F> struct mp_fold_Q8
  71. {
  72. template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
  73. using fn = F<F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>;
  74. };
  75. template<class V, template<class...> class F> struct mp_fold_Q9
  76. {
  77. template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
  78. using fn = F<F<F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>;
  79. };
  80. //
  81. template<template<class...> class L, class T1, class V, template<class...> class F>
  82. struct mp_fold_impl<L<T1>, V, F>: mp_defer<mp_fold_Q1<V, F>::template fn, T1>
  83. {
  84. };
  85. template<template<class...> class L, class T1, class T2, class V, template<class...> class F>
  86. struct mp_fold_impl<L<T1, T2>, V, F>: mp_defer<mp_fold_Q2<V, F>::template fn, T1, T2>
  87. {
  88. };
  89. template<template<class...> class L, class T1, class T2, class T3, class V, template<class...> class F>
  90. struct mp_fold_impl<L<T1, T2, T3>, V, F>: mp_defer<mp_fold_Q3<V, F>::template fn, T1, T2, T3>
  91. {
  92. };
  93. template<template<class...> class L, class T1, class T2, class T3, class T4, class V, template<class...> class F>
  94. struct mp_fold_impl<L<T1, T2, T3, T4>, V, F>: mp_defer<mp_fold_Q4<V, F>::template fn, T1, T2, T3, T4>
  95. {
  96. };
  97. template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class V, template<class...> class F>
  98. struct mp_fold_impl<L<T1, T2, T3, T4, T5>, V, F>: mp_defer<mp_fold_Q5<V, F>::template fn, T1, T2, T3, T4, T5>
  99. {
  100. };
  101. template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class V, template<class...> class F>
  102. struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6>, V, F>: mp_defer<mp_fold_Q6<V, F>::template fn, T1, T2, T3, T4, T5, T6>
  103. {
  104. };
  105. template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class V, template<class...> class F>
  106. struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7>, V, F>: mp_defer<mp_fold_Q7<V, F>::template fn, T1, T2, T3, T4, T5, T6, T7>
  107. {
  108. };
  109. template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class V, template<class...> class F>
  110. struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8>, V, F>: mp_defer<mp_fold_Q8<V, F>::template fn, T1, T2, T3, T4, T5, T6, T7, T8>
  111. {
  112. };
  113. template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class V, template<class...> class F>
  114. struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9>, V, F>: mp_defer<mp_fold_Q9<V, F>::template fn, T1, T2, T3, T4, T5, T6, T7, T8, T9>
  115. {
  116. };
  117. //
  118. template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, class V, template<class...> class F>
  119. struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, V, F>
  120. {
  121. using type = typename mp_fold_impl<L<T...>, F<F<F<F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>, T10>, F>::type;
  122. };
  123. } // namespace detail
  124. template<class L, class V, template<class...> class F> using mp_fold = typename detail::mp_fold_impl<L, V, F>::type;
  125. template<class L, class V, class Q> using mp_fold_q = mp_fold<L, V, Q::template fn>;
  126. } // namespace mp11
  127. } // namespace bho
  128. #endif // #ifndef BHO_MP11_DETAIL_MP_FOLD_HPP_INCLUDED