/*============================================================================= 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 repeatedly do this until the function can /// finally be called. By default, `partial` captures all of its variables by /// value, just like bind. `std::ref` can be used to capture references /// instead. /// /// Synopsis /// -------- /// /// template /// constexpr partial_adaptor partial(F f); /// /// Semantics /// --------- /// /// assert(partial(f)(xs...)(ys...) == f(xs..., ys...)); /// /// Requirements /// ------------ /// /// F must be: /// /// * [Callable](concepts.md#callable) /// * 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 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 FIT_SFINAE_RESULT ( typename result_of, result_of...> >::type, id_ ) operator()(Ts&&... xs) const FIT_SFINAE_RETURNS ( fit::pack_join ( FIT_MANGLE_CAST(const Pack&)(FIT_CONST_THIS->get_pack(xs...)), fit::pack_forward(FIT_FORWARD(Ts)(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::value >::type> constexpr auto operator()(Ts&&... xs) const FIT_SFINAE_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(Ts)(xs)...)) ) ); }; template struct partial_adaptor_pack { constexpr partial_adaptor_pack() {} template constexpr const F& get_function(Ts&&...) const { return static_cast(static_cast(*this)); } FIT_RETURNS_CLASS(partial_adaptor_pack); template::value >::type> constexpr auto operator()(Ts&&... xs) const FIT_SFINAE_RETURNS ( partial ( FIT_RETURNS_C_CAST(F&&)(FIT_CONST_THIS->get_function(xs...)), fit::pack_decay(FIT_FORWARD(Ts)(xs)...) ) ); }; template struct partial_adaptor_base { typedef conditional_adaptor < partial_adaptor_invoke, F, Pack>, partial_adaptor_join, F, Pack> > type; }; template struct partial_adaptor_pack_base { typedef conditional_adaptor < F, partial_adaptor_pack > type; }; } template struct partial_adaptor : detail::partial_adaptor_base::type, F, Pack { typedef typename detail::partial_adaptor_base::type base; typedef partial_adaptor fit_rewritable1_tag; 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)(x)), Pack(FIT_FORWARD(S)(seq)) {} }; template struct partial_adaptor : detail::partial_adaptor_pack_base, detail::callable_base>::type { typedef typename detail::partial_adaptor_pack_base, detail::callable_base>::type base; typedef partial_adaptor fit_rewritable1_tag; template constexpr const detail::callable_base& base_function(Ts&&...) const { return *this; } using base::operator(); FIT_INHERIT_CONSTRUCTOR(partial_adaptor, base); }; // Make partial_adaptor work with pipable_adaptor by removing its pipableness template struct partial_adaptor, void> : partial_adaptor { typedef partial_adaptor base; typedef partial_adaptor fit_rewritable1_tag; FIT_INHERIT_CONSTRUCTOR(partial_adaptor, base); }; template struct partial_adaptor>, void> : partial_adaptor { typedef partial_adaptor base; typedef partial_adaptor fit_rewritable1_tag; FIT_INHERIT_CONSTRUCTOR(partial_adaptor, base); }; } // namespace fit #endif