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 89namespace boost { namespace hof { namespace detail { 90 91struct 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> 102 constexpr State operator()(const F&, State&& state) const noexcept 103 { 104 return BOOST_HOF_FORWARD(State)(state); 105 } 106}; 107 108} 109 110template<class F, class State=void> 111struct 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; 115 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> 124 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 144template<class F> 145struct reverse_fold_adaptor<F, void> 146: detail::callable_base<F> 147{ 148 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 169BOOST_HOF_DECLARE_STATIC_VAR(reverse_fold, detail::make<reverse_fold_adaptor>); 170 171}} // namespace boost::hof 172 173#endif 174