Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*=============================================================================
0002     Copyright (c) 2012 Paul Fultz II
0003     pipable.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_FUNCTION_PIPABLE_H
0009 #define BOOST_HOF_GUARD_FUNCTION_PIPABLE_H
0010 
0011 /// pipable
0012 /// =======
0013 /// 
0014 /// Description
0015 /// -----------
0016 /// 
0017 /// The `pipable` function adaptor provides an extension method. The first
0018 /// parameter of the function can be piped into the function using the pipe
0019 /// `|` operator. This can be especially convenient when there are a lot of
0020 /// nested function calls. Functions that are made pipable can still be called
0021 /// the traditional way without piping in the first parameter.
0022 /// 
0023 /// Synopsis
0024 /// --------
0025 /// 
0026 ///     template<class F>
0027 ///     constexpr pipable_adaptor<F> pipable(F f);
0028 /// 
0029 /// Semantics
0030 /// ---------
0031 /// 
0032 ///     assert(x | pipable(f)(ys...) == f(x, ys...));
0033 /// 
0034 /// Requirements
0035 /// ------------
0036 /// 
0037 /// F must be:
0038 /// 
0039 /// * [ConstInvocable](ConstInvocable)
0040 /// * MoveConstructible
0041 /// 
0042 /// Example
0043 /// -------
0044 /// 
0045 ///     #include <boost/hof.hpp>
0046 ///     #include <cassert>
0047 ///     using namespace boost::hof;
0048 /// 
0049 ///     struct sum
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(3 == (1 | pipable(sum())(2)));
0060 ///         assert(3 == pipable(sum())(1, 2));
0061 ///     }
0062 /// 
0063 /// References
0064 /// ----------
0065 /// 
0066 /// * [Extension methods](<Extension methods>)
0067 /// 
0068 
0069 #include <boost/hof/first_of.hpp>
0070 #include <boost/hof/pack.hpp>
0071 #include <boost/hof/detail/delegate.hpp>
0072 #include <boost/hof/detail/move.hpp>
0073 #include <boost/hof/detail/make.hpp>
0074 #include <boost/hof/detail/static_const_var.hpp>
0075 #include <boost/hof/limit.hpp>
0076 
0077 namespace boost { namespace hof { 
0078  
0079 template<class F>
0080 struct pipable_adaptor;
0081 
0082 namespace detail {
0083 
0084 template<class F, class Pack>
0085 struct pipe_closure : F, Pack
0086 {
0087     
0088     template<class X, class P>
0089     constexpr pipe_closure(X&& fp, P&& packp) 
0090     BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(F, X&&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(Pack, P&&))
0091     : F(BOOST_HOF_FORWARD(X)(fp)), Pack(BOOST_HOF_FORWARD(P)(packp))
0092     {}
0093 
0094     template<class... Ts>
0095     constexpr const F& base_function(Ts&&...) const noexcept
0096     {
0097         return *this;
0098     }
0099 
0100     template<class... Ts>
0101     constexpr const Pack& get_pack(Ts&&...) const noexcept
0102     {
0103         return *this;
0104     }
0105 
0106     template<class A>
0107     struct invoke
0108     {
0109         A a;
0110         const pipe_closure * self;
0111         template<class X>
0112         constexpr invoke(X&& xp, const pipe_closure * selfp) 
0113         BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(A, X&&))
0114         : a(BOOST_HOF_FORWARD(X)(xp)), self(selfp)
0115         {}
0116 
0117         BOOST_HOF_RETURNS_CLASS(invoke);
0118 
0119         template<class... Ts>
0120         constexpr BOOST_HOF_SFINAE_RESULT(const F&, id_<A>, id_<Ts>...) 
0121         operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
0122         (BOOST_HOF_RETURNS_STATIC_CAST(const F&)(*BOOST_HOF_CONST_THIS->self)(BOOST_HOF_FORWARD(A)(a), BOOST_HOF_FORWARD(Ts)(xs)...));
0123     };
0124 
0125     BOOST_HOF_RETURNS_CLASS(pipe_closure);
0126 
0127     template<class A>
0128     constexpr BOOST_HOF_SFINAE_RESULT(const Pack&, id_<invoke<A&&>>) 
0129     operator()(A&& a) const BOOST_HOF_SFINAE_RETURNS
0130     (BOOST_HOF_MANGLE_CAST(const Pack&)(BOOST_HOF_CONST_THIS->get_pack(a))(invoke<A&&>(BOOST_HOF_FORWARD(A)(a), BOOST_HOF_CONST_THIS)));
0131 };
0132 
0133 template<class F, class Pack>
0134 constexpr auto make_pipe_closure(F f, Pack&& p) BOOST_HOF_RETURNS
0135 (
0136     pipe_closure<F, typename std::remove_reference<Pack>::type>(BOOST_HOF_RETURNS_STATIC_CAST(F&&)(f), BOOST_HOF_FORWARD(Pack)(p))
0137 );
0138 
0139 
0140 template<class Derived, class F>
0141 struct pipe_pack
0142 {
0143     template<class... Ts>
0144     constexpr const F& get_function(Ts&&...) const noexcept
0145     {
0146         return static_cast<const F&>(static_cast<const Derived&>(*this));
0147     }
0148 
0149     BOOST_HOF_RETURNS_CLASS(pipe_pack);
0150 
0151     template<class... Ts, class=typename std::enable_if<
0152         (sizeof...(Ts) < function_param_limit<F>::value)
0153     >::type>
0154     constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
0155     (make_pipe_closure(BOOST_HOF_RETURNS_C_CAST(F&&)(BOOST_HOF_CONST_THIS->get_function(xs...)), boost::hof::pack_forward(BOOST_HOF_FORWARD(Ts)(xs)...)));
0156 };
0157     
0158 template<class A, class F, class Pack>
0159 constexpr auto operator|(A&& a, const pipe_closure<F, Pack>& p) BOOST_HOF_RETURNS
0160 (p(BOOST_HOF_FORWARD(A)(a)));
0161 
0162 }
0163 
0164 template<class F>
0165 struct pipable_adaptor 
0166 : detail::basic_first_of_adaptor<detail::callable_base<F>, detail::pipe_pack<pipable_adaptor<F>, detail::callable_base<F>> >
0167 {
0168     typedef detail::basic_first_of_adaptor<detail::callable_base<F>, detail::pipe_pack<pipable_adaptor<F>, detail::callable_base<F>> > base;
0169     typedef pipable_adaptor fit_rewritable_tag;
0170 
0171     BOOST_HOF_INHERIT_CONSTRUCTOR(pipable_adaptor, base);
0172 
0173     constexpr const detail::callable_base<F>& base_function() const noexcept
0174     {
0175         return *this;
0176     }
0177 };
0178 
0179 template<class A, class F>
0180 constexpr auto operator|(A&& a, const pipable_adaptor<F>& p) BOOST_HOF_RETURNS
0181 (p(BOOST_HOF_FORWARD(A)(a)));
0182 
0183 BOOST_HOF_DECLARE_STATIC_VAR(pipable, detail::make<pipable_adaptor>);
0184 
0185 namespace detail {
0186 
0187 template<class F>
0188 struct static_function_wrapper;
0189 
0190 // Operators for static_function_wrapper adaptor
0191 template<class A, class F>
0192 auto operator|(A&& a, const boost::hof::detail::static_function_wrapper<F>& f) BOOST_HOF_RETURNS
0193 (f(BOOST_HOF_FORWARD(A)(a)));
0194 
0195 template<class F>
0196 struct static_default_function;
0197 
0198 // Operators for static_default_function adaptor
0199 template<class A, class F>
0200 auto operator|(A&& a, const boost::hof::detail::static_default_function<F>& f) BOOST_HOF_RETURNS
0201 (f(BOOST_HOF_FORWARD(A)(a)));
0202 
0203 }
0204 
0205 template<class F>
0206 struct static_;
0207 
0208 // Operators for static_ adaptor
0209 template<class A, class F>
0210 auto operator|(A&& a, static_<F> f) BOOST_HOF_RETURNS
0211 (f.base_function().base_function()(BOOST_HOF_FORWARD(A)(a)));
0212 
0213 }} // namespace boost::hof
0214 
0215 #endif