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_while.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_WHILE_H
0009 #define BOOST_HOF_GUARD_REPEAT_WHILE_H
0010 
0011 /// repeat_while
0012 /// ======
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The `repeat_while` function decorator will repeatedly apply a function while
0018 /// the predicate returns a boolean that is true. If the predicate returns an
0019 /// `IntergralConstant` then the predicate is only evaluated at compile-time.
0020 /// 
0021 /// 
0022 /// Synopsis
0023 /// --------
0024 /// 
0025 ///     template<class Predicate>
0026 ///     constexpr auto repeat_while(Predicate predicate);
0027 /// 
0028 /// Requirements
0029 /// ------------
0030 /// 
0031 /// Predicate must be:
0032 /// 
0033 /// * [ConstFunctionObject](ConstFunctionObject)
0034 /// * MoveConstructible
0035 /// 
0036 /// Example
0037 /// -------
0038 /// 
0039 ///     #include <boost/hof.hpp>
0040 ///     #include <cassert>
0041 /// 
0042 ///     struct increment
0043 ///     {
0044 ///         template<class T>
0045 ///         constexpr std::integral_constant<int, T::value + 1> operator()(T) const
0046 ///         {
0047 ///             return std::integral_constant<int, T::value + 1>();
0048 ///         }
0049 ///     };
0050 /// 
0051 ///     struct not_6
0052 ///     {
0053 ///         template<class T>
0054 ///         constexpr std::integral_constant<bool, (T::value != 6)> 
0055 ///         operator()(T) const
0056 ///         {
0057 ///             return std::integral_constant<bool, (T::value != 6)>();
0058 ///         }
0059 ///     };
0060 /// 
0061 ///     typedef std::integral_constant<int, 1> one;
0062 ///     typedef std::integral_constant<int, 6> six;
0063 /// 
0064 ///     int main() {
0065 ///         auto increment_until_6 = boost::hof::repeat_while(not_6())(increment());
0066 ///         static_assert(std::is_same<six, decltype(increment_until_6(one()))>::value, "Error");
0067 ///     }
0068 /// 
0069 
0070 #include <boost/hof/always.hpp>
0071 #include <boost/hof/detail/delegate.hpp>
0072 #include <boost/hof/detail/result_of.hpp>
0073 #include <boost/hof/detail/move.hpp>
0074 #include <boost/hof/decorate.hpp>
0075 #include <boost/hof/detail/static_const_var.hpp>
0076 #include <boost/hof/first_of.hpp>
0077 #include <boost/hof/detail/recursive_constexpr_depth.hpp>
0078 
0079 namespace boost { namespace hof { namespace detail {
0080 
0081 template<class P, class... Ts>
0082 struct compute_predicate
0083 {
0084     typedef decltype(std::declval<P>()(std::declval<Ts>()...)) type;
0085 };
0086 
0087 template<bool B>
0088 struct while_repeater
0089 {
0090     template<class F, class P, class... Ts>
0091     constexpr BOOST_HOF_SFINAE_RESULT(while_repeater<
0092         compute_predicate<P, typename result_of<const F&, id_<Ts>...>::type>::type::value
0093     >, id_<const F&>, id_<const P&>, result_of<const F&, id_<Ts>...>) 
0094     operator()(const F& f, const P& p, Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
0095     (
0096         while_repeater<
0097             compute_predicate<P, decltype(f(BOOST_HOF_FORWARD(Ts)(xs)...))>::type::value
0098         >()(f, p, f(BOOST_HOF_FORWARD(Ts)(xs)...))
0099     );
0100 };
0101 
0102 template<>
0103 struct while_repeater<false>
0104 {
0105     template<class F, class P, class T>
0106     constexpr T operator()(const F&, const P&, T&& x) const 
0107     BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(x)
0108     {
0109         return x;
0110     }
0111 };
0112 
0113 struct repeat_while_constant_decorator
0114 {
0115     template<class P, class F, class... Ts>
0116     constexpr auto operator()(const P& p, const F& f, Ts&&... xs) const BOOST_HOF_RETURNS
0117     (
0118         detail::while_repeater<
0119             detail::compute_predicate<P, decltype(std::declval<F>()(BOOST_HOF_FORWARD(Ts)(xs)...))>::type::value
0120         >()
0121         (
0122             f, 
0123             p, 
0124             BOOST_HOF_FORWARD(Ts)(xs)...
0125         )
0126     );
0127 };
0128 
0129 template<int Depth>
0130 struct repeat_while_integral_decorator
0131 {
0132     template<class P, class F, class T, class... Ts, class Self=repeat_while_integral_decorator<Depth-1>>
0133     constexpr auto operator()(const P& p, const F& f, T&& x, Ts&&... xs) const BOOST_HOF_RETURNS
0134     (
0135         (p(x, BOOST_HOF_FORWARD(Ts)(xs)...)) ? 
0136             Self()(
0137                 p, 
0138                 f, 
0139                 f(x, BOOST_HOF_FORWARD(Ts)(xs)...)
0140             ) : 
0141             BOOST_HOF_FORWARD(T)(x)
0142     );
0143 };
0144 
0145 template<>
0146 struct repeat_while_integral_decorator<0>
0147 {
0148     template<class P, class F, class T, class Self=repeat_while_integral_decorator<0>>
0149 #if BOOST_HOF_HAS_RELAXED_CONSTEXPR
0150     constexpr
0151 #endif
0152     auto operator()(const P& p, const F& f, T x) const 
0153     BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT((p(x), f(x)))
0154     -> decltype(f(x))
0155     {
0156         while(p(x))
0157         {
0158             // TODO: Should move?
0159             x = f(x);
0160         }
0161         return x;
0162     }
0163 };
0164 }
0165 
0166 #if BOOST_HOF_HAS_RELAXED_CONSTEXPR
0167 #define BOOST_HOF_REPEAT_WHILE_CONSTEXPR_DEPTH 1
0168 #else
0169 #define BOOST_HOF_REPEAT_WHILE_CONSTEXPR_DEPTH BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH
0170 #endif
0171 
0172 BOOST_HOF_DECLARE_STATIC_VAR(repeat_while, decorate_adaptor<
0173     boost::hof::first_of_adaptor<
0174         detail::repeat_while_constant_decorator,
0175         detail::repeat_while_integral_decorator<BOOST_HOF_REPEAT_WHILE_CONSTEXPR_DEPTH>
0176     >
0177 >);
0178 
0179 }} // namespace boost::hof
0180 
0181 #endif