/*============================================================================= Copyright (c) 2015 Paul Fultz II repeat.h Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #ifndef BOOST_HOF_GUARD_REPEAT_H #define BOOST_HOF_GUARD_REPEAT_H /// repeat /// ====== /// /// Description /// ----------- /// /// The `repeat` function decorator will repeatedly apply a function a given /// number of times. /// /// /// Synopsis /// -------- /// /// template /// constexpr auto repeat(Integral); /// /// Semantics /// --------- /// /// assert(repeat(std::integral_constant{})(f)(xs...) == f(xs...)); /// assert(repeat(std::integral_constant{})(f)(xs...) == f(f(xs...))); /// assert(repeat(0)(f)(xs...) == f(xs...)); /// assert(repeat(1)(f)(xs...) == f(f(xs...))); /// /// Requirements /// ------------ /// /// Integral must be: /// /// * Integral /// /// Or: /// /// * IntegralConstant /// /// Example /// ------- /// /// #include /// #include /// /// struct increment /// { /// template /// constexpr T operator()(T x) const /// { /// return x + 1; /// } /// }; /// /// int main() { /// auto increment_by_5 = boost::hof::repeat(std::integral_constant())(increment()); /// assert(increment_by_5(1) == 6); /// } /// #include #include #include #include #include #include #include #include namespace boost { namespace hof { namespace detail { template struct repeater { template constexpr BOOST_HOF_SFINAE_RESULT(repeater, id_, result_of...>) operator()(const F& f, Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS ( repeater()(f, f(BOOST_HOF_FORWARD(Ts)(xs)...)) ); }; template<> struct repeater<0> { template constexpr T operator()(const F&, T&& x) const BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(T(x)) { return x; } }; struct repeat_constant_decorator { template constexpr auto operator()(Integral, const F& f, Ts&&... xs) const BOOST_HOF_RETURNS ( detail::repeater() ( f, BOOST_HOF_FORWARD(Ts)(xs)... ) ); }; template struct repeat_integral_decorator { template> constexpr auto operator()(Integral n, const F& f, T&& x, Ts&&... xs) const BOOST_HOF_RETURNS ( (n) ? Self()(n-1, f, f(BOOST_HOF_FORWARD(T)(x), BOOST_HOF_FORWARD(Ts)(xs)...)) : BOOST_HOF_FORWARD(T)(x) ); }; template<> struct repeat_integral_decorator<0> { template> #if BOOST_HOF_HAS_RELAXED_CONSTEXPR constexpr #endif auto operator()(Integral n, const F& f, T x) const BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT((n--, f(BOOST_HOF_FORWARD(T)(x)))) -> decltype(f(BOOST_HOF_FORWARD(T)(x))) { while(n > 0) { n--; x = f(BOOST_HOF_FORWARD(T)(x)); } return x; } // TODO: Add overload for lvalue }; } #if BOOST_HOF_HAS_RELAXED_CONSTEXPR #define BOOST_HOF_REPEAT_CONSTEXPR_DEPTH 1 #else #define BOOST_HOF_REPEAT_CONSTEXPR_DEPTH BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH #endif BOOST_HOF_DECLARE_STATIC_VAR(repeat, decorate_adaptor< boost::hof::first_of_adaptor< detail::repeat_constant_decorator, detail::repeat_integral_decorator >>); }} // namespace boost::hof #endif