⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 do_the_bind.cpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 CPP
字号:
/*=============================================================================    Copyright (c) 2006-2007 Tobias Schwinger      Use modification and distribution are subject to 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).    Problem:    How to "do the Bind?"    This recipe shows how to implement a function binder, similar to     Boost.Bind based on the Functional module of Fusion.    It works as follows:    'bind' is a global, stateless function object. It is implemented in    fused form (fused_binder) and transformed into a variadic function     object. When called, 'bind' returns another function object, which    holds the arguments of the call to 'bind'. It is, again, implemented     in fused form (fused_bound_function) and transformed into unfused    form. ==============================================================================*/#include <boost/fusion/functional/invocation/invoke.hpp>#include <boost/fusion/functional/adapter/unfused_generic.hpp>#include <boost/fusion/functional/adapter/unfused_rvalue_args.hpp>#include <boost/fusion/support/deduce_sequence.hpp>#include <boost/fusion/sequence/intrinsic/at.hpp>#include <boost/fusion/mpl.hpp>#include <boost/fusion/sequence/intrinsic/front.hpp>#include <boost/fusion/sequence/intrinsic/empty.hpp>#include <boost/fusion/algorithm/transformation/transform.hpp>#include <boost/fusion/algorithm/transformation/pop_front.hpp>#include <boost/type_traits/remove_reference.hpp>#include <boost/mpl/eval_if.hpp>#include <boost/mpl/identity.hpp>#include <boost/mpl/int.hpp>#include <boost/ref.hpp>#include <iostream>#include <typeinfo>namespace impl{    namespace fusion = boost::fusion;    namespace traits = boost::fusion::traits;    namespace result_of = boost::fusion::result_of;    namespace mpl = boost::mpl;    using mpl::placeholders::_;    // Placeholders (we inherit from mpl::int_, so we can use placeholders    // as indices for fusion::at, later)     template <int I> struct placeholder : mpl::int_<I> { };    // A traits class to find out whether T is a placeholeder    template <typename T> struct is_placeholder              : mpl::false_  { };    template <int I> struct is_placeholder< placeholder<I> > : mpl::true_   { };    template <int I> struct is_placeholder< placeholder<I> & > : mpl::true_   { };    template <int I> struct is_placeholder< placeholder<I> const   > : mpl::true_   { };    template <int I> struct is_placeholder< placeholder<I> const & > : mpl::true_   { };    // This class template provides a Polymorphic Function Object to be used    // with fusion::transform. It is applied to the sequence of arguments that    // describes the binding and holds a reference to the sequence of arguments     // from the final call.     template<class FinalArgs> struct argument_transform    {        FinalArgs const & ref_final_args;    public:        explicit argument_transform(FinalArgs const & final_args)            : ref_final_args(final_args)        { }        // A placeholder? Replace it with an argument from the final call...        template <int Index>        inline typename result_of::at_c<FinalArgs const, Index>::type        operator()(placeholder<Index> const &) const        {            return fusion::at_c<Index>(this->ref_final_args);        }        // ...just return the bound argument, otherwise.        template <typename T> inline T & operator()(T & bound) const        {            return bound;        }        template <typename Signature>        struct result;        template <class Self, typename T>        struct result< Self (T) >            : mpl::eval_if< is_placeholder<T>,                 result_of::at<FinalArgs,typename boost::remove_reference<T>::type>,                mpl::identity<T>            >        { };    };    // Fused implementation of the bound function, the function object     // returned by bind    template <class BindArgs> class fused_bound_function     {        typedef typename traits::deduce_sequence<BindArgs>::type bound_args;        bound_args fsq_bind_args;    public:        fused_bound_function(BindArgs const & bind_args)          : fsq_bind_args(bind_args)        { }        template <typename Signature>        struct result;        template <class FinalArgs>        struct result_impl            : result_of::invoke< typename result_of::front<bound_args>::type,                typename result_of::transform<                    typename result_of::pop_front<bound_args>::type,                    argument_transform<FinalArgs> const                 >::type            >        { };         template <class Self, class FinalArgs>        struct result< Self (FinalArgs) >            : result_impl< typename boost::remove_reference<FinalArgs>::type >         { };        template <class FinalArgs>        inline typename result_impl<FinalArgs>::type         operator()(FinalArgs const & final_args) const        {            return fusion::invoke( fusion::front(this->fsq_bind_args),                fusion::transform( fusion::pop_front(this->fsq_bind_args),                    argument_transform<FinalArgs>(final_args) ) );        }        // Could add a non-const variant - omitted for readability    };    // Fused implementation of the 'bind' function    struct fused_binder    {        template <class Signature>        struct result;        template <class BindArgs>        struct result_impl        {            // We have to transform the arguments so they are held by-value            // in the returned function.             typedef fusion::unfused_generic<                 fused_bound_function<BindArgs> > type;        };        template <class Self, class BindArgs>        struct result< Self (BindArgs) >            : result_impl< typename boost::remove_reference<BindArgs>::type >        { };        template <class BindArgs>        inline typename result_impl< BindArgs >::type         operator()(BindArgs & bind_args) const        {            return typename result< void(BindArgs) >::type(bind_args);        }    };    // The binder's unfused type. We use unfused_rvalue_args to make that    // thing more similar to Boost.Bind. Because of that we have to use     // Boost.Ref (below in the sample code)    typedef fusion::unfused_rvalue_args<fused_binder> binder;}// Placeholder globalsimpl::placeholder<0> const _1_ = impl::placeholder<0>();impl::placeholder<1> const _2_ = impl::placeholder<1>();impl::placeholder<2> const _3_ = impl::placeholder<2>();impl::placeholder<3> const _4_ = impl::placeholder<3>();// The bind function is a global, tooimpl::binder const bind = impl::binder();// OK, let's try it out:struct func{    typedef int result_type;    inline int operator()() const    {        std::cout << "operator()" << std::endl;        return 0;    }    template <typename A>     inline int operator()(A const & a) const    {        std::cout << "operator()(A const & a)" << std::endl;        std::cout << "  a = " << a << "  A = " << typeid(A).name() << std::endl;        return 1;    }    template <typename A, typename B>     inline int operator()(A const & a, B & b) const    {        std::cout << "operator()(A const & a, B & b)" << std::endl;        std::cout << "  a = " << a << "  A = " << typeid(A).name() << std::endl;        std::cout << "  b = " << b << "  B = " << typeid(B).name() << std::endl;        return 2;    }};int main(){    func f;    int value = 42;    using boost::ref;    int errors = 0;    errors += !( bind(f)() == 0);    errors += !( bind(f,"Hi")() == 1);    errors += !( bind(f,_1_)("there.") == 1);    errors += !( bind(f,"The answer is",_1_)(value) == 2);    errors += !( bind(f,_1_,ref(value))("Really?") == 2);    errors += !( bind(f,_1_,_2_)("Dunno. If there is an answer, it's",value) == 2);    return !! errors;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -