1 /*============================================================================= 2 Copyright (c) 2015 Paul Fultz II 3 reverse_fold.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_REVERSE_FOLD_H 9 #define BOOST_HOF_GUARD_REVERSE_FOLD_H 10 11 /// reverse_fold 12 /// ======== 13 /// 14 /// Description 15 /// ----------- 16 /// 17 /// The `reverse_fold` function adaptor uses a binary function to apply a 18 /// reverse [fold] 19 /// (https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29)(ie right 20 /// fold in functional programming terms) operation to the arguments passed to 21 /// the function. Additionally, an optional initial state can be provided, 22 /// otherwise the first argument is used as the initial state. 23 /// 24 /// The arguments to the binary function, take first the state and then the 25 /// argument. 26 /// 27 /// Synopsis 28 /// -------- 29 /// 30 /// template<class F, class State> 31 /// constexpr reverse_fold_adaptor<F, State> reverse_fold(F f, State s); 32 /// 33 /// template<class F> 34 /// constexpr reverse_fold_adaptor<F> reverse_fold(F f); 35 /// 36 /// Semantics 37 /// --------- 38 /// 39 /// assert(reverse_fold(f, z)() == z); 40 /// assert(reverse_fold(f, z)(x, xs...) == f(reverse_fold(f, z)(xs...), x)); 41 /// assert(reverse_fold(f)(x) == x); 42 /// assert(reverse_fold(f)(x, xs...) == f(reverse_fold(f)(xs...), x)); 43 /// 44 /// Requirements 45 /// ------------ 46 /// 47 /// State must be: 48 /// 49 /// * CopyConstructible 50 /// 51 /// F must be: 52 /// 53 /// * [BinaryInvocable](BinaryInvocable) 54 /// * MoveConstructible 55 /// 56 /// Example 57 /// ------- 58 /// 59 /// #include <boost/hof.hpp> 60 /// #include <cassert> 61 /// 62 /// struct max_f 63 /// { 64 /// template<class T, class U> 65 /// constexpr T operator()(T x, U y) const 66 /// { 67 /// return x > y ? x : y; 68 /// } 69 /// }; 70 /// 71 /// int main() { 72 /// assert(boost::hof::reverse_fold(max_f())(2, 3, 4, 5) == 5); 73 /// } 74 /// 75 /// References 76 /// ---------- 77 /// 78 /// * [Projections](Projections) 79 /// * [Variadic print](<Variadic print>) 80 /// 81 82 #include <boost/hof/detail/callable_base.hpp> 83 #include <boost/hof/detail/delegate.hpp> 84 #include <boost/hof/detail/compressed_pair.hpp> 85 #include <boost/hof/detail/move.hpp> 86 #include <boost/hof/detail/make.hpp> 87 #include <boost/hof/detail/static_const_var.hpp> 88 89 namespace boost { namespace hof { namespace detail { 90 91 struct v_reverse_fold 92 { 93 BOOST_HOF_RETURNS_CLASS(v_reverse_fold); 94 template<class F, class State, class T, class... Ts> 95 constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(const F&, result_of<const v_reverse_fold&, id_<const F&>, id_<State>, id_<Ts>...>, id_<T>) 96 operator()(const F& f, State&& state, T&& x, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS 97 ( 98 f((*BOOST_HOF_CONST_THIS)(f, BOOST_HOF_FORWARD(State)(state), BOOST_HOF_FORWARD(Ts)(xs)...), BOOST_HOF_FORWARD(T)(x)) 99 ); 100 101 template<class F, class State> operator ()boost::hof::detail::v_reverse_fold102 constexpr State operator()(const F&, State&& state) const noexcept 103 { 104 return BOOST_HOF_FORWARD(State)(state); 105 } 106 }; 107 108 } 109 110 template<class F, class State=void> 111 struct reverse_fold_adaptor 112 : detail::compressed_pair<detail::callable_base<F>, State> 113 { 114 typedef detail::compressed_pair<detail::callable_base<F>, State> base_type; BOOST_HOF_INHERIT_CONSTRUCTORboost::hof::reverse_fold_adaptor115 BOOST_HOF_INHERIT_CONSTRUCTOR(reverse_fold_adaptor, base_type) 116 117 template<class... Ts> 118 constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept 119 { 120 return this->first(xs...); 121 } 122 123 template<class... Ts> get_stateboost::hof::reverse_fold_adaptor124 constexpr State get_state(Ts&&... xs) const noexcept 125 { 126 return this->second(xs...); 127 } 128 129 BOOST_HOF_RETURNS_CLASS(reverse_fold_adaptor); 130 131 template<class... Ts> 132 constexpr BOOST_HOF_SFINAE_RESULT(detail::v_reverse_fold, id_<const detail::callable_base<F>&>, id_<State>, id_<Ts>...) 133 operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS 134 ( 135 detail::v_reverse_fold()( 136 BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)), 137 BOOST_HOF_MANGLE_CAST(State)(BOOST_HOF_CONST_THIS->get_state(xs...)), 138 BOOST_HOF_FORWARD(Ts)(xs)... 139 ) 140 ) 141 }; 142 143 144 template<class F> 145 struct reverse_fold_adaptor<F, void> 146 : detail::callable_base<F> 147 { BOOST_HOF_INHERIT_CONSTRUCTORboost::hof::reverse_fold_adaptor148 BOOST_HOF_INHERIT_CONSTRUCTOR(reverse_fold_adaptor, detail::callable_base<F>) 149 150 template<class... Ts> 151 constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept 152 { 153 return boost::hof::always_ref(*this)(xs...); 154 } 155 156 BOOST_HOF_RETURNS_CLASS(reverse_fold_adaptor); 157 158 template<class... Ts> 159 constexpr BOOST_HOF_SFINAE_RESULT(detail::v_reverse_fold, id_<const detail::callable_base<F>&>, id_<Ts>...) 160 operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS 161 ( 162 detail::v_reverse_fold()( 163 BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)), 164 BOOST_HOF_FORWARD(Ts)(xs)... 165 ) 166 ) 167 }; 168 169 BOOST_HOF_DECLARE_STATIC_VAR(reverse_fold, detail::make<reverse_fold_adaptor>); 170 171 }} // namespace boost::hof 172 173 #endif 174