Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*=============================================================================
0002     Copyright (c) 2015 Paul Fultz II
0003     reverse_fold.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_REVERSE_FOLD_H
0009 #define BOOST_HOF_GUARD_REVERSE_FOLD_H
0010 
0011 /// reverse_fold
0012 /// ========
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The `reverse_fold` function adaptor uses a binary function to apply a
0018 /// reverse [fold]
0019 /// (https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29)(ie right
0020 /// fold in functional programming terms) operation to the arguments passed to
0021 /// the function. Additionally, an optional initial state can be provided,
0022 /// otherwise the first argument is used as the initial state.
0023 /// 
0024 /// The arguments to the binary function, take first the state and then the
0025 /// argument.
0026 /// 
0027 /// Synopsis
0028 /// --------
0029 /// 
0030 ///     template<class F, class State>
0031 ///     constexpr reverse_fold_adaptor<F, State> reverse_fold(F f, State s);
0032 /// 
0033 ///     template<class F>
0034 ///     constexpr reverse_fold_adaptor<F> reverse_fold(F f);
0035 /// 
0036 /// Semantics
0037 /// ---------
0038 /// 
0039 ///     assert(reverse_fold(f, z)() == z);
0040 ///     assert(reverse_fold(f, z)(x, xs...) == f(reverse_fold(f, z)(xs...), x));
0041 ///     assert(reverse_fold(f)(x) == x);
0042 ///     assert(reverse_fold(f)(x, xs...) == f(reverse_fold(f)(xs...), x));
0043 /// 
0044 /// Requirements
0045 /// ------------
0046 /// 
0047 /// State must be:
0048 /// 
0049 /// * CopyConstructible
0050 /// 
0051 /// F must be:
0052 /// 
0053 /// * [BinaryInvocable](BinaryInvocable)
0054 /// * MoveConstructible
0055 /// 
0056 /// Example
0057 /// -------
0058 /// 
0059 ///     #include <boost/hof.hpp>
0060 ///     #include <cassert>
0061 /// 
0062 ///     struct max_f
0063 ///     {
0064 ///         template<class T, class U>
0065 ///         constexpr T operator()(T x, U y) const
0066 ///         {
0067 ///             return x > y ? x : y;
0068 ///         }
0069 ///     };
0070 /// 
0071 ///     int main() {
0072 ///         assert(boost::hof::reverse_fold(max_f())(2, 3, 4, 5) == 5);
0073 ///     }
0074 /// 
0075 /// References
0076 /// ----------
0077 /// 
0078 /// * [Projections](Projections)
0079 /// * [Variadic print](<Variadic print>)
0080 /// 
0081 
0082 #include <boost/hof/detail/callable_base.hpp>
0083 #include <boost/hof/detail/delegate.hpp>
0084 #include <boost/hof/detail/compressed_pair.hpp>
0085 #include <boost/hof/detail/move.hpp>
0086 #include <boost/hof/detail/make.hpp>
0087 #include <boost/hof/detail/static_const_var.hpp>
0088 
0089 namespace boost { namespace hof { namespace detail {
0090 
0091 struct v_reverse_fold
0092 {
0093     BOOST_HOF_RETURNS_CLASS(v_reverse_fold);
0094     template<class F, class State, class T, class... Ts>
0095     constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(const F&, result_of<const v_reverse_fold&, id_<const F&>, id_<State>, id_<Ts>...>, id_<T>)
0096     operator()(const F& f, State&& state, T&& x, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS
0097     (
0098         f((*BOOST_HOF_CONST_THIS)(f, BOOST_HOF_FORWARD(State)(state), BOOST_HOF_FORWARD(Ts)(xs)...), BOOST_HOF_FORWARD(T)(x))
0099     );
0100 
0101     template<class F, class State>
0102     constexpr State operator()(const F&, State&& state) const noexcept
0103     {
0104         return BOOST_HOF_FORWARD(State)(state);
0105     }
0106 };
0107 
0108 }
0109 
0110 template<class F, class State=void>
0111 struct reverse_fold_adaptor
0112 : detail::compressed_pair<detail::callable_base<F>, State>
0113 {
0114     typedef detail::compressed_pair<detail::callable_base<F>, State> base_type;
0115     BOOST_HOF_INHERIT_CONSTRUCTOR(reverse_fold_adaptor, base_type)
0116 
0117     template<class... Ts>
0118     constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
0119     {
0120         return this->first(xs...);
0121     }
0122 
0123     template<class... Ts>
0124     constexpr State get_state(Ts&&... xs) const noexcept
0125     {
0126         return this->second(xs...);
0127     }
0128 
0129     BOOST_HOF_RETURNS_CLASS(reverse_fold_adaptor);
0130 
0131     template<class... Ts>
0132     constexpr BOOST_HOF_SFINAE_RESULT(detail::v_reverse_fold, id_<const detail::callable_base<F>&>, id_<State>, id_<Ts>...)
0133     operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
0134     (
0135         detail::v_reverse_fold()(
0136             BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)), 
0137             BOOST_HOF_MANGLE_CAST(State)(BOOST_HOF_CONST_THIS->get_state(xs...)), 
0138             BOOST_HOF_FORWARD(Ts)(xs)...
0139         )
0140     )
0141 };
0142 
0143 
0144 template<class F>
0145 struct reverse_fold_adaptor<F, void>
0146 : detail::callable_base<F>
0147 {
0148     BOOST_HOF_INHERIT_CONSTRUCTOR(reverse_fold_adaptor, detail::callable_base<F>)
0149 
0150     template<class... Ts>
0151     constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const noexcept
0152     {
0153         return boost::hof::always_ref(*this)(xs...);
0154     }
0155 
0156     BOOST_HOF_RETURNS_CLASS(reverse_fold_adaptor);
0157 
0158     template<class... Ts>
0159     constexpr BOOST_HOF_SFINAE_RESULT(detail::v_reverse_fold, id_<const detail::callable_base<F>&>, id_<Ts>...)
0160     operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
0161     (
0162         detail::v_reverse_fold()(
0163             BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)), 
0164             BOOST_HOF_FORWARD(Ts)(xs)...
0165         )
0166     )
0167 };
0168 
0169 BOOST_HOF_DECLARE_STATIC_VAR(reverse_fold, detail::make<reverse_fold_adaptor>);
0170 
0171 }} // namespace boost::hof
0172 
0173 #endif