repeat.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*=============================================================================
  2. Copyright (c) 2015 Paul Fultz II
  3. repeat.h
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #ifndef BOOST_HOF_GUARD_REPEAT_H
  8. #define BOOST_HOF_GUARD_REPEAT_H
  9. /// repeat
  10. /// ======
  11. ///
  12. /// Description
  13. /// -----------
  14. ///
  15. /// The `repeat` function decorator will repeatedly apply a function a given
  16. /// number of times.
  17. ///
  18. ///
  19. /// Synopsis
  20. /// --------
  21. ///
  22. /// template<class Integral>
  23. /// constexpr auto repeat(Integral);
  24. ///
  25. /// Semantics
  26. /// ---------
  27. ///
  28. /// assert(repeat(std::integral_constant<int, 0>{})(f)(xs...) == f(xs...));
  29. /// assert(repeat(std::integral_constant<int, 1>{})(f)(xs...) == f(f(xs...)));
  30. /// assert(repeat(0)(f)(xs...) == f(xs...));
  31. /// assert(repeat(1)(f)(xs...) == f(f(xs...)));
  32. ///
  33. /// Requirements
  34. /// ------------
  35. ///
  36. /// Integral must be:
  37. ///
  38. /// * Integral
  39. ///
  40. /// Or:
  41. ///
  42. /// * IntegralConstant
  43. ///
  44. /// Example
  45. /// -------
  46. ///
  47. /// #include <boost/hof.hpp>
  48. /// #include <cassert>
  49. ///
  50. /// struct increment
  51. /// {
  52. /// template<class T>
  53. /// constexpr T operator()(T x) const
  54. /// {
  55. /// return x + 1;
  56. /// }
  57. /// };
  58. ///
  59. /// int main() {
  60. /// auto increment_by_5 = boost::hof::repeat(std::integral_constant<int, 5>())(increment());
  61. /// assert(increment_by_5(1) == 6);
  62. /// }
  63. ///
  64. #include <boost/hof/always.hpp>
  65. #include <boost/hof/detail/delegate.hpp>
  66. #include <boost/hof/detail/result_of.hpp>
  67. #include <boost/hof/detail/move.hpp>
  68. #include <boost/hof/detail/static_const_var.hpp>
  69. #include <boost/hof/decorate.hpp>
  70. #include <boost/hof/first_of.hpp>
  71. #include <boost/hof/detail/recursive_constexpr_depth.hpp>
  72. namespace boost { namespace hof { namespace detail {
  73. template<int N>
  74. struct repeater
  75. {
  76. template<class F, class... Ts>
  77. constexpr BOOST_HOF_SFINAE_RESULT(repeater<N-1>, id_<const F&>, result_of<const F&, id_<Ts>...>)
  78. operator()(const F& f, Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
  79. (
  80. repeater<N-1>()(f, f(BOOST_HOF_FORWARD(Ts)(xs)...))
  81. );
  82. };
  83. template<>
  84. struct repeater<0>
  85. {
  86. template<class F, class T>
  87. constexpr T operator()(const F&, T&& x) const
  88. BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(T(x))
  89. {
  90. return x;
  91. }
  92. };
  93. struct repeat_constant_decorator
  94. {
  95. template<class Integral, class F, class... Ts>
  96. constexpr auto operator()(Integral, const F& f, Ts&&... xs) const BOOST_HOF_RETURNS
  97. (
  98. detail::repeater<Integral::type::value>()
  99. (
  100. f,
  101. BOOST_HOF_FORWARD(Ts)(xs)...
  102. )
  103. );
  104. };
  105. template<int Depth>
  106. struct repeat_integral_decorator
  107. {
  108. template<class Integral, class F, class T, class... Ts, class Self=repeat_integral_decorator<Depth-1>>
  109. constexpr auto operator()(Integral n, const F& f, T&& x, Ts&&... xs) const BOOST_HOF_RETURNS
  110. (
  111. (n) ?
  112. Self()(n-1, f, f(BOOST_HOF_FORWARD(T)(x), BOOST_HOF_FORWARD(Ts)(xs)...)) :
  113. BOOST_HOF_FORWARD(T)(x)
  114. );
  115. };
  116. template<>
  117. struct repeat_integral_decorator<0>
  118. {
  119. template<class Integral, class F, class T, class Self=repeat_integral_decorator<0>>
  120. #if BOOST_HOF_HAS_RELAXED_CONSTEXPR
  121. constexpr
  122. #endif
  123. auto operator()(Integral n, const F& f, T x) const
  124. BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT((n--, f(BOOST_HOF_FORWARD(T)(x))))
  125. -> decltype(f(BOOST_HOF_FORWARD(T)(x)))
  126. {
  127. while(n > 0)
  128. {
  129. n--;
  130. x = f(BOOST_HOF_FORWARD(T)(x));
  131. }
  132. return x;
  133. }
  134. // TODO: Add overload for lvalue
  135. };
  136. }
  137. #if BOOST_HOF_HAS_RELAXED_CONSTEXPR
  138. #define BOOST_HOF_REPEAT_CONSTEXPR_DEPTH 1
  139. #else
  140. #define BOOST_HOF_REPEAT_CONSTEXPR_DEPTH BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH
  141. #endif
  142. BOOST_HOF_DECLARE_STATIC_VAR(repeat, decorate_adaptor<
  143. boost::hof::first_of_adaptor<
  144. detail::repeat_constant_decorator,
  145. detail::repeat_integral_decorator<BOOST_HOF_REPEAT_CONSTEXPR_DEPTH>
  146. >>);
  147. }} // namespace boost::hof
  148. #endif