Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:43:50

0001 /*=============================================================================
0002     Copyright (c) 2015 Paul Fultz II
0003     apply_eval.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_APPLY_EVAL_H
0009 #define BOOST_HOF_GUARD_APPLY_EVAL_H
0010 
0011 /// apply_eval
0012 /// ==========
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The `apply_eval` function work like [`apply`](/include/boost/hof/apply), except it calls
0018 /// [`eval`](/include/boost/hof/eval) on each of its arguments. Each [`eval`](/include/boost/hof/eval) call is
0019 /// always ordered from left-to-right.
0020 /// 
0021 /// Synopsis
0022 /// --------
0023 /// 
0024 ///     template<class F, class... Ts>
0025 ///     constexpr auto apply_eval(F&& f, Ts&&... xs);
0026 /// 
0027 /// Semantics
0028 /// ---------
0029 /// 
0030 ///     assert(apply_eval(f)(xs...) == f(eval(xs)...));
0031 /// 
0032 /// Requirements
0033 /// ------------
0034 /// 
0035 /// F must be:
0036 /// 
0037 /// * [ConstInvocable](ConstInvocable)
0038 /// 
0039 /// Ts must be:
0040 /// 
0041 /// * [EvaluatableFunctionObject](EvaluatableFunctionObject)
0042 /// 
0043 /// Example
0044 /// -------
0045 /// 
0046 ///     #include <boost/hof.hpp>
0047 ///     #include <cassert>
0048 /// 
0049 ///     struct sum_f
0050 ///     {
0051 ///         template<class T, class U>
0052 ///         T operator()(T x, U y) const
0053 ///         {
0054 ///             return x+y;
0055 ///         }
0056 ///     };
0057 /// 
0058 ///     int main() {
0059 ///         assert(boost::hof::apply_eval(sum_f(), []{ return 1; }, []{ return 2; }) == 3);
0060 ///     }
0061 /// 
0062 
0063 #include <boost/hof/config.hpp>
0064 #include <boost/hof/returns.hpp>
0065 #include <boost/hof/detail/forward.hpp>
0066 #include <boost/hof/detail/static_const_var.hpp>
0067 #include <boost/hof/apply.hpp>
0068 #include <boost/hof/eval.hpp>
0069 
0070 #if BOOST_HOF_NO_ORDERED_BRACE_INIT
0071 #include <boost/hof/pack.hpp>
0072 #include <boost/hof/capture.hpp>
0073 #endif
0074 
0075 namespace boost { namespace hof {
0076 
0077 namespace detail {
0078 
0079 #if BOOST_HOF_NO_ORDERED_BRACE_INIT
0080 template<class R, class F, class Pack>
0081 constexpr R eval_ordered(const F& f, Pack&& p)
0082 {
0083     return p(f);
0084 }
0085 
0086 template<class R, class F, class Pack, class T, class... Ts>
0087 constexpr R eval_ordered(const F& f, Pack&& p, T&& x, Ts&&... xs)
0088 {
0089     return boost::hof::detail::eval_ordered<R>(f, boost::hof::pack_join(BOOST_HOF_FORWARD(Pack)(p), boost::hof::pack_forward(boost::hof::eval(x))), BOOST_HOF_FORWARD(Ts)(xs)...);
0090 }
0091 #else
0092 template<class R>
0093 struct eval_helper
0094 {
0095     R result;
0096 
0097     template<class F, class... Ts>
0098     constexpr eval_helper(const F& f, Ts&&... xs) : result(boost::hof::apply(f, BOOST_HOF_FORWARD(Ts)(xs)...))
0099     {}
0100 };
0101 
0102 template<>
0103 struct eval_helper<void>
0104 {
0105     int x;
0106     template<class F, class... Ts>
0107     constexpr eval_helper(const F& f, Ts&&... xs) : x((boost::hof::apply(f, BOOST_HOF_FORWARD(Ts)(xs)...), 0))
0108     {}
0109 };
0110 #endif
0111 
0112 struct apply_eval_f
0113 {
0114     template<class F, class... Ts, class R=decltype(
0115         boost::hof::apply(std::declval<const F&>(), boost::hof::eval(std::declval<Ts>())...)
0116     ),
0117     class=typename std::enable_if<(!std::is_void<R>::value)>::type 
0118     >
0119     constexpr R operator()(const F& f, Ts&&... xs) const BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(boost::hof::apply(f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...))
0120     {
0121         return
0122 #if BOOST_HOF_NO_ORDERED_BRACE_INIT
0123         boost::hof::detail::eval_ordered<R>
0124             (f, boost::hof::pack(), BOOST_HOF_FORWARD(Ts)(xs)...);
0125 #else
0126         boost::hof::detail::eval_helper<R>
0127             {f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...}.result;
0128 #endif
0129     }
0130 
0131     template<class F, class... Ts, class R=decltype(
0132         boost::hof::apply(std::declval<const F&>(), boost::hof::eval(std::declval<Ts>())...)
0133     ),
0134     class=typename std::enable_if<(std::is_void<R>::value)>::type 
0135     >
0136     constexpr typename detail::holder<Ts...>::type 
0137     operator()(const F& f, Ts&&... xs) const BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(boost::hof::apply(f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...))
0138     {
0139         return (typename detail::holder<Ts...>::type)
0140 #if BOOST_HOF_NO_ORDERED_BRACE_INIT
0141         boost::hof::detail::eval_ordered<R>
0142             (f, boost::hof::pack(), BOOST_HOF_FORWARD(Ts)(xs)...);
0143 #else
0144         boost::hof::detail::eval_helper<R>
0145             {f, boost::hof::eval(BOOST_HOF_FORWARD(Ts)(xs))...};
0146 #endif
0147     }
0148 };
0149 
0150 }
0151 
0152 BOOST_HOF_DECLARE_STATIC_VAR(apply_eval, detail::apply_eval_f);
0153 
0154 }} // namespace boost::hof
0155 
0156 #endif