/*============================================================================= Copyright (c) 2012 Paul Fultz II partial.h Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #ifndef FIT_GUARD_FUNCTION_PARTIAL_H #define FIT_GUARD_FUNCTION_PARTIAL_H /// partial /// ======== /// /// Description /// ----------- /// /// The `partial` function adaptor allows partial application of the function. /// If the function can not be called with all the parameters, it will return /// another function. It will continually do this until the function can /// finally be called. By default, `partial` captures all of it variables by /// value, just like bind. `std::ref` can be used to capture references /// instead. /// /// Synopsis /// -------- /// /// template /// constexpr partial_adaptor partial(F f); /// /// Requirements /// ------------ /// /// F must be: /// /// FunctionObject /// MoveConstructible /// /// Example /// ------- /// /// struct sum /// { /// template /// T operator()(T x, U y) const /// { /// return x+y; /// } /// }; /// /// assert(3 == partial(sum())(1)(2)); /// #include #include #include #include #include #include #include namespace fit { // TODO: Get rid of sequence parameter // Forward declare partial_adaptor, since it will be used below template struct partial_adaptor; FIT_DECLARE_STATIC_VAR(partial, detail::make); namespace detail { template struct partial_adaptor_invoke { template constexpr const F& get_function(Ts&&...) const { return static_cast(static_cast(*this)); } template constexpr const Pack& get_pack(Ts&&...) const { return static_cast(static_cast(*this)); } FIT_RETURNS_CLASS(partial_adaptor_invoke); template constexpr auto operator()(Ts&&... xs) const FIT_RETURNS ( fit::pack_join ( FIT_MANGLE_CAST(const Pack&)(FIT_CONST_THIS->get_pack(xs...)), fit::pack_forward(fit::forward(xs)...) ) (FIT_RETURNS_C_CAST(F&&)(FIT_CONST_THIS->get_function(xs...))) ); }; template struct partial_adaptor_join { template constexpr const F& get_function(Ts&&...) const { return static_cast(static_cast(*this)); } template constexpr const Pack& get_pack(Ts&&...) const { return static_cast(static_cast(*this)); } FIT_RETURNS_CLASS(partial_adaptor_join); template constexpr auto operator()(Ts&&... xs) const FIT_RETURNS ( partial ( FIT_RETURNS_C_CAST(F&&)(FIT_CONST_THIS->get_function(xs...)), fit::pack_join(FIT_MANGLE_CAST(const Pack&)(FIT_CONST_THIS->get_pack(xs...)), fit::pack_decay(fit::forward(xs)...)) ) ); }; template struct partial_adaptor_pack { template constexpr const F& get_function(Ts&&...) const { return static_cast(static_cast(*this)); } FIT_RETURNS_CLASS(partial_adaptor_pack); template constexpr auto operator()(Ts&&... xs) const FIT_RETURNS ( partial ( FIT_RETURNS_C_CAST(F&&)(FIT_CONST_THIS->get_function(xs...)), fit::pack_decay(fit::forward(xs)...) ) ); }; template struct partial_adaptor_base { typedef conditional_adaptor < partial_adaptor_invoke, F, Pack>, partial_adaptor_join, F, Pack> > type; }; template struct partial_adaptor_base { typedef conditional_adaptor < F, partial_adaptor_pack, F> > type; }; } template struct partial_adaptor : detail::partial_adaptor_base::type, F, Pack { typedef typename detail::partial_adaptor_base::type base; template constexpr const F& base_function(Ts&&...) const { return *this; } constexpr const Pack& get_pack() const { return *this; } using base::operator(); constexpr partial_adaptor() {} template constexpr partial_adaptor(X&& x, S&& seq) : F(fit::forward(x)), Pack(fit::forward(seq)) {} }; template struct partial_adaptor : detail::partial_adaptor_base::type { typedef typename detail::partial_adaptor_base::type base; template constexpr const F& base_function(Ts&&...) const { return *this; } using base::operator(); constexpr partial_adaptor() {} template constexpr partial_adaptor(X&& x) : base(fit::forward(x)) {} }; // Make partial_adaptor work with pipable_adaptor by removing its pipableness template struct partial_adaptor, void> : partial_adaptor { typedef partial_adaptor base; constexpr partial_adaptor() {} template constexpr partial_adaptor(X&& x) : base(fit::forward(x)) {} }; template struct partial_adaptor>, void> : partial_adaptor { typedef partial_adaptor base; partial_adaptor() {} template partial_adaptor(X&& x) : base(fit::forward(x)) {} }; } #endif