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