Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:16

0001 /*=============================================================================
0002     Copyright (c) 2015 Paul Fultz II
0003     repeat.h
0004     Distributed under the Boost Software License, Version 1.0. (See accompanying
0005     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 ==============================================================================*/
0007 
0008 #ifndef BOOST_HOF_GUARD_REPEAT_H
0009 #define BOOST_HOF_GUARD_REPEAT_H
0010 
0011 /// repeat
0012 /// ======
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The `repeat` function decorator will repeatedly apply a function a given
0018 /// number of times.
0019 /// 
0020 /// 
0021 /// Synopsis
0022 /// --------
0023 /// 
0024 ///     template<class Integral>
0025 ///     constexpr auto repeat(Integral);
0026 /// 
0027 /// Semantics
0028 /// ---------
0029 /// 
0030 ///     assert(repeat(std::integral_constant<int, 0>{})(f)(xs...) == f(xs...));
0031 ///     assert(repeat(std::integral_constant<int, 1>{})(f)(xs...) == f(f(xs...)));
0032 ///     assert(repeat(0)(f)(xs...) == f(xs...));
0033 ///     assert(repeat(1)(f)(xs...) == f(f(xs...)));
0034 /// 
0035 /// Requirements
0036 /// ------------
0037 /// 
0038 /// Integral must be:
0039 /// 
0040 /// * Integral
0041 /// 
0042 /// Or:
0043 /// 
0044 /// * IntegralConstant
0045 /// 
0046 /// Example
0047 /// -------
0048 /// 
0049 ///     #include <boost/hof.hpp>
0050 ///     #include <cassert>
0051 /// 
0052 ///     struct increment
0053 ///     {
0054 ///         template<class T>
0055 ///         constexpr T operator()(T x) const
0056 ///         {
0057 ///             return x + 1;
0058 ///         }
0059 ///     };
0060 /// 
0061 ///     int main() {
0062 ///         auto increment_by_5 = boost::hof::repeat(std::integral_constant<int, 5>())(increment());
0063 ///         assert(increment_by_5(1) == 6);
0064 ///     }
0065 /// 
0066 
0067 #include <boost/hof/always.hpp>
0068 #include <boost/hof/detail/delegate.hpp>
0069 #include <boost/hof/detail/result_of.hpp>
0070 #include <boost/hof/detail/move.hpp>
0071 #include <boost/hof/detail/static_const_var.hpp>
0072 #include <boost/hof/decorate.hpp>
0073 #include <boost/hof/first_of.hpp>
0074 #include <boost/hof/detail/recursive_constexpr_depth.hpp>
0075 
0076 namespace boost { namespace hof { namespace detail {
0077 
0078 template<int N>
0079 struct repeater
0080 {
0081     template<class F, class... Ts>
0082     constexpr BOOST_HOF_SFINAE_RESULT(repeater<N-1>, id_<const F&>, result_of<const F&, id_<Ts>...>) 
0083     operator()(const F& f, Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
0084     (
0085         repeater<N-1>()(f, f(BOOST_HOF_FORWARD(Ts)(xs)...))
0086     );
0087 };
0088 
0089 template<>
0090 struct repeater<0>
0091 {
0092     template<class F, class T>
0093     constexpr T operator()(const F&, T&& x) const
0094     BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(T(x))
0095     {
0096         return x;
0097     }
0098 };
0099 
0100 struct repeat_constant_decorator
0101 {
0102     template<class Integral, class F, class... Ts>
0103     constexpr auto operator()(Integral, const F& f, Ts&&... xs) const BOOST_HOF_RETURNS
0104     (
0105         detail::repeater<Integral::type::value>()
0106         (
0107             f, 
0108             BOOST_HOF_FORWARD(Ts)(xs)...
0109         )
0110     );
0111 };
0112 
0113 template<int Depth>
0114 struct repeat_integral_decorator
0115 {
0116     template<class Integral, class F, class T, class... Ts, class Self=repeat_integral_decorator<Depth-1>>
0117     constexpr auto operator()(Integral n, const F& f, T&& x, Ts&&... xs) const BOOST_HOF_RETURNS
0118     (
0119         (n) ? 
0120             Self()(n-1, f, f(BOOST_HOF_FORWARD(T)(x), BOOST_HOF_FORWARD(Ts)(xs)...)) :
0121             BOOST_HOF_FORWARD(T)(x)
0122     );
0123 };
0124 
0125 template<>
0126 struct repeat_integral_decorator<0>
0127 {
0128     template<class Integral, class F, class T, class Self=repeat_integral_decorator<0>>
0129 #if BOOST_HOF_HAS_RELAXED_CONSTEXPR
0130     constexpr
0131 #endif
0132     auto operator()(Integral n, const F& f, T x) const 
0133     BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT((n--, f(BOOST_HOF_FORWARD(T)(x))))
0134     -> decltype(f(BOOST_HOF_FORWARD(T)(x)))
0135     {
0136         while(n > 0)
0137         {
0138             n--;
0139             x = f(BOOST_HOF_FORWARD(T)(x));
0140         }
0141         return x;
0142     }
0143     // TODO: Add overload for lvalue
0144 };
0145 
0146 }
0147 
0148 #if BOOST_HOF_HAS_RELAXED_CONSTEXPR
0149 #define BOOST_HOF_REPEAT_CONSTEXPR_DEPTH 1
0150 #else
0151 #define BOOST_HOF_REPEAT_CONSTEXPR_DEPTH BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH
0152 #endif
0153 
0154 BOOST_HOF_DECLARE_STATIC_VAR(repeat, decorate_adaptor<
0155     boost::hof::first_of_adaptor<
0156     detail::repeat_constant_decorator, 
0157     detail::repeat_integral_decorator<BOOST_HOF_REPEAT_CONSTEXPR_DEPTH>
0158 >>);
0159 
0160 }} // namespace boost::hof
0161 
0162 #endif