| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 | /*=============================================================================    Copyright (c) 2015 Paul Fultz II    apply.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 BOOST_HOF_GUARD_APPLY_H#define BOOST_HOF_GUARD_APPLY_H/// apply/// =====/// /// Description/// -----------/// /// The `apply` function calls the function given to it with its arguments./// /// Synopsis/// --------/// ///     template<class F, class... Ts>///     constexpr auto apply(F&& f, Ts&&... xs);/// /// Semantics/// ---------/// ///     assert(apply(f)(xs...) == f(xs...));///     assert(fold(apply, f)(x, y, z) == f(x)(y)(z));/// /// Requirements/// ------------/// /// F must be:/// /// * [Invocable](Invocable)/// /// Example/// -------/// ///     #include <boost/hof.hpp>///     #include <cassert>/// ///     struct sum_f///     {///         template<class T, class U>///         T operator()(T x, U y) const///         {///             return x+y;///         }///     };/// ///     int main() {///         assert(boost::hof::apply(sum_f(), 1, 2) == 3);///     }/// #include <boost/hof/detail/result_of.hpp>#include <boost/hof/detail/forward.hpp>#include <boost/hof/detail/static_const_var.hpp>#ifdef _MSC_VER#pragma warning(push)#pragma warning(disable: 4003)#endif#define BOOST_HOF_DETAIL_FOREACH_QUAL(m, data) \    m(, data) \    m(const, data) \    m(volatile, data) \    m(const volatile, data)namespace boost { namespace hof {namespace detail {#if BOOST_HOF_HAS_MANUAL_DEDUCTION || BOOST_HOF_NO_EXPRESSION_SFINAEstruct apply_mem_fn{    template<class...>    struct convertible_args;    template<class T, class U, class=void>    struct is_convertible_args    : std::false_type    {};    template<class... Ts, class... Us>    struct is_convertible_args<        convertible_args<Ts...>,         convertible_args<Us...>,         typename std::enable_if<(            sizeof...(Ts) == sizeof...(Us)        )>::type    >    : and_<std::is_convertible<Ts, Us>...>    {};    template<class From, class To>    struct is_compatible    : std::is_convertible<        typename std::add_pointer<typename std::remove_reference<From>::type>::type,        typename std::add_pointer<typename std::remove_reference<To>::type>::type    >    {};#define BOOST_HOF_APPLY_MEM_FN_CALL(cv, data) \    template <class R, class Base, class Derived, class... Ts, class... Us, class=typename std::enable_if<and_< \        is_compatible<Derived, cv Base>, \        is_convertible_args<convertible_args<Us...>, convertible_args<Ts...>> \    >::value>::type> \    constexpr R operator()(R (Base::*mf)(Ts...) cv, Derived&& ref, Us &&... xs) const \    BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT((BOOST_HOF_FORWARD(Derived)(ref).*mf)(BOOST_HOF_FORWARD(Us)(xs)...)) \    { \        return (BOOST_HOF_FORWARD(Derived)(ref).*mf)(BOOST_HOF_FORWARD(Us)(xs)...); \    }    BOOST_HOF_DETAIL_FOREACH_QUAL(BOOST_HOF_APPLY_MEM_FN_CALL, ~)};struct apply_mem_data{    template<class T, class R>    struct match_qualifier    { typedef R type; };#define BOOST_HOF_APPLY_MEM_DATA_MATCH(cv, ref) \    template<class T, class R> \    struct match_qualifier<cv T ref, R> \    : match_qualifier<T, cv R ref> \    {};    BOOST_HOF_DETAIL_FOREACH_QUAL(BOOST_HOF_APPLY_MEM_DATA_MATCH,&)    BOOST_HOF_DETAIL_FOREACH_QUAL(BOOST_HOF_APPLY_MEM_DATA_MATCH,&&)    template <class Base, class R, class Derived, class=typename std::enable_if<(        std::is_base_of<Base, typename std::decay<Derived>::type>::value    )>::type>    constexpr typename match_qualifier<Derived, R>::type     operator()(R Base::*pmd, Derived&& ref) const noexcept    {        return BOOST_HOF_FORWARD(Derived)(ref).*pmd;    }};template<class T, class U=decltype(*std::declval<T>())>struct apply_deref{ typedef U type; };#endifstruct apply_f{#if BOOST_HOF_HAS_MANUAL_DEDUCTION || BOOST_HOF_NO_EXPRESSION_SFINAE    template<class F, class T, class... Ts, class=typename std::enable_if<(        std::is_member_function_pointer<typename std::decay<F>::type>::value    )>::type>    constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_fn, id_<F>, id_<T>, id_<Ts>...)     operator()(F&& f, T&& obj, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS    (        apply_mem_fn()(f, BOOST_HOF_FORWARD(T)(obj), BOOST_HOF_FORWARD(Ts)(xs)...)    );    template<class F, class T, class... Ts, class U=typename apply_deref<T>::type, class=typename std::enable_if<(        std::is_member_function_pointer<typename std::decay<F>::type>::value    )>::type>    constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_fn, id_<F>, id_<U>, id_<Ts>...)     operator()(F&& f, T&& obj, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS    (        apply_mem_fn()(f, *BOOST_HOF_FORWARD(T)(obj), BOOST_HOF_FORWARD(Ts)(xs)...)    );    template<class F, class T, class... Ts, class=typename std::enable_if<(        std::is_member_function_pointer<typename std::decay<F>::type>::value    )>::type>    constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_fn, id_<F>, id_<T&>, id_<Ts>...)     operator()(F&& f, const std::reference_wrapper<T>& ref, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS    (        apply_mem_fn()(f, ref.get(), BOOST_HOF_FORWARD(Ts)(xs)...)    );    template<class F, class T, class=typename std::enable_if<(        std::is_member_object_pointer<typename std::decay<F>::type>::value    )>::type>    constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_data, id_<F>, id_<T>)     operator()(F&& f, T&& obj) const BOOST_HOF_SFINAE_MANUAL_RETURNS    (        apply_mem_data()(f, BOOST_HOF_FORWARD(T)(obj))    );    template<class F, class T, class U=typename apply_deref<T>::type, class=typename std::enable_if<(        std::is_member_object_pointer<typename std::decay<F>::type>::value    )>::type>    constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_data, id_<F>, id_<U>)     operator()(F&& f, T&& obj) const BOOST_HOF_SFINAE_MANUAL_RETURNS    (        apply_mem_data()(f, *BOOST_HOF_FORWARD(T)(obj))    );        template<class F, class T, class=typename std::enable_if<(        std::is_member_object_pointer<typename std::decay<F>::type>::value    )>::type>    constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(apply_mem_data, id_<F>, id_<T&>)     operator()(F&& f, const std::reference_wrapper<T>& ref) const BOOST_HOF_SFINAE_MANUAL_RETURNS    (        apply_mem_data()(f, ref.get())    );#else    template <class Base, class T, class Derived>    constexpr auto operator()(T Base::*pmd, Derived&& ref) const    BOOST_HOF_RETURNS(BOOST_HOF_FORWARD(Derived)(ref).*pmd);         template <class PMD, class Pointer>    constexpr auto operator()(PMD&& pmd, Pointer&& ptr) const    BOOST_HOF_RETURNS((*BOOST_HOF_FORWARD(Pointer)(ptr)).*BOOST_HOF_FORWARD(PMD)(pmd));    template <class Base, class T, class Derived>    constexpr auto operator()(T Base::*pmd, const std::reference_wrapper<Derived>& ref) const    BOOST_HOF_RETURNS(ref.get().*pmd);         template <class Base, class T, class Derived, class... Args>    constexpr auto operator()(T Base::*pmf, Derived&& ref, Args&&... args) const    BOOST_HOF_RETURNS((BOOST_HOF_FORWARD(Derived)(ref).*pmf)(BOOST_HOF_FORWARD(Args)(args)...));         template <class PMF, class Pointer, class... Args>    constexpr auto operator()(PMF&& pmf, Pointer&& ptr, Args&&... args) const    BOOST_HOF_RETURNS(((*BOOST_HOF_FORWARD(Pointer)(ptr)).*BOOST_HOF_FORWARD(PMF)(pmf))(BOOST_HOF_FORWARD(Args)(args)...));    template <class Base, class T, class Derived, class... Args>    constexpr auto operator()(T Base::*pmf, const std::reference_wrapper<Derived>& ref, Args&&... args) const    BOOST_HOF_RETURNS((ref.get().*pmf)(BOOST_HOF_FORWARD(Args)(args)...));#endif    template<class F, class... Ts>    constexpr BOOST_HOF_SFINAE_MANUAL_RESULT(F, id_<Ts>...)     operator()(F&& f, Ts&&... xs) const BOOST_HOF_SFINAE_MANUAL_RETURNS    (        f(BOOST_HOF_FORWARD(Ts)(xs)...)    );};}BOOST_HOF_DECLARE_STATIC_VAR(apply, detail::apply_f);}} // namespace boost::hof#ifdef _MSC_VER#pragma warning(pop)#endif#endif
 |