Ticket #4569: unfused.patch

File unfused.patch, 10.0 KB (added by anonymous, 12 years ago)
  • unfused.hpp

     
    3131
    3232namespace boost { namespace fusion
    3333{
    34     template <class Function, bool AllowNullary = true>
    35     class unfused;
     34    template <class Derived, template<typename> class Result, bool AllowNullary = true>
     35    class unfuse_interface;
    3636
    3737    //----- ---- --- -- - -  -   -
    3838
    39     template <class Function>
    40     class unfused<Function,true>
    41       : public unfused<Function,false>
     39    template <class Derived, template<typename> class Result>
     40    class unfuse_interface<Derived,Result,true>
     41      : public unfuse_interface<Derived,Result,false>
    4242    {
    43         typedef typename detail::qf_c<Function>::type function_c;
    44         typedef typename detail::qf<Function>::type function;
    45         typedef typename detail::call_param<Function>::type func_const_fwd_t;
    4643      public:
     44        using unfuse_interface<Derived,Result,false>::operator();
    4745
    48         using unfused<Function,false>::operator();
     46        template<typename Sig>
     47        struct result
     48            : unfuse_interface<Derived,Result,false>::result<Sig>{};
    4949
    50         inline explicit unfused(func_const_fwd_t f = function())
    51             : unfused<Function,false>(f)
    52         { }
     50        template<typename Self>
     51        struct result<Self()>
     52            : Result<Derived (fusion::vector0<> &)>{};
    5353
    54         typedef typename boost::result_of<
    55             function_c(fusion::vector0<> &) >::type call_const_0_result;
     54        template<typename Self>
     55        struct result<Self const ()>
     56            : Result<Derived const (fusion::vector0<> &)>{};
    5657
    57         inline call_const_0_result operator()() const
     58        inline typename result<Derived const ()>::type operator()() const
    5859        {
    5960            fusion::vector0<> arg;
    60             return this->fnc_transformed(arg);
     61            return static_cast<Derived const *>(this)->call(arg);
    6162        }
    6263
    63         typedef typename boost::result_of<
    64             function(fusion::vector0<> &) >::type call_0_result;
    65 
    66         inline call_0_result operator()()
     64        inline typename result<Derived ()>::type operator()()
    6765        {
    6866            fusion::vector0<> arg;
    69             return this->fnc_transformed(arg);
     67            return static_cast<Derived *>(this)->call(arg);
    7068        }
    7169    };
    7270
    73     template <class Function> class unfused<Function,false>
     71    template <class Derived, template<typename> class Result>
     72    class unfuse_interface<Derived, Result,false>
    7473    {
    75       protected:
    76         Function fnc_transformed;
    77         typedef typename detail::qf_c<Function>::type function_c;
    78         typedef typename detail::qf<Function>::type function;
    79         typedef typename detail::call_param<Function>::type func_const_fwd_t;
    8074      public:
    81 
    82         inline explicit unfused(func_const_fwd_t f = function())
    83             : fnc_transformed(f)
    84         { }
    85 
    8675        template <typename Sig>
    8776        struct result;
    8877
     
    9180        #define  BOOST_PP_ITERATION_LIMITS \
    9281            (1,BOOST_FUSION_UNFUSED_MAX_ARITY)
    9382        #include BOOST_PP_ITERATE()
     83
     84        //perfect forwarding for up to 2 arguments:
     85        template <typename T0,typename T1>
     86        inline typename result< Derived const (T0 const &,T1 &) >::type
     87        operator()(T0 const &a0,T1 &a1) const{
     88            fusion::vector2<T0 const &,T1 &> arg(a0,a1);
     89            return static_cast<Derived const *>(this)->call(arg);
     90        }
     91        template <typename T0,typename T1>
     92        inline typename result< Derived const (T0 const &,T1 &) >::type
     93        operator()(T0 const &a0,T1 &a1){
     94            fusion::vector2<T0 const &,T1 &> arg(a0,a1);
     95            return static_cast<Derived *>(this)->call(arg);
     96        }
     97        template <typename T0,typename T1>
     98        inline typename result< Derived const (T0 &,T1 const &) >::type
     99        operator()(T0 &a0,T1 const &a1) const{
     100            fusion::vector2<T0 &,T1 const &> arg(a0,a1);
     101            return static_cast<Derived const *>(this)->call(arg);
     102        }
     103        template <typename T0,typename T1>
     104        inline typename result< Derived const (T0 &,T1 const &) >::type
     105        operator()(T0 &a0,T1 const &a1){
     106            fusion::vector2<T0 &,T1 const &> arg(a0,a1);
     107            return static_cast<Derived *>(this)->call(arg);
     108        }
    94109    };
     110
     111    namespace detail{
     112   
     113        template<typename Function>
     114        struct fused_result{
     115            typedef typename detail::qf_c<Function>::type function_c;
     116            typedef typename detail::qf<Function>::type function;
     117            template<typename Sig>
     118            struct result;
     119            template<typename Self,typename Seq>
     120            struct result<Self const (Seq &)>
     121                : boost::result_of< function_c (Seq &) >{};
     122            template<typename Self,typename Seq>
     123            struct result<Self (Seq &)>
     124                : boost::result_of< function (Seq &) >{};
     125        };
     126    }
     127
     128    template <class Function, bool AllowNullary = true>
     129    class unfused
     130        : public unfuse_interface<
     131            unfused<Function,AllowNullary>,
     132            typename detail::fused_result<Function>::template result,
     133            AllowNullary>{
     134        typedef typename detail::call_param<Function>::type func_const_fwd_t;
     135    public:
     136        inline explicit unfused(func_const_fwd_t f = function())
     137            : fnc_transformed(f)
     138        { }
     139    private:
     140        Function fnc_transformed;
     141        template<class,template<typename> class,bool>
     142        friend class unfuse_interface;
     143        template<typename Seq>
     144        typename detail::fused_result<Function>::template result<unfused (Seq &)>::type
     145        call(Seq &seq){
     146            return fnc_transformed(seq);
     147        }
     148        template<typename Seq>
     149        typename detail::fused_result<Function>::template result<unfused const (Seq &)>::type
     150        call(Seq &seq) const{
     151            return fnc_transformed(seq);
     152        }
     153
     154    };
     155
    95156}}
    96157
    97158#if defined (BOOST_MSVC)
    98159#  pragma warning(pop)
    99160#endif
    100161
    101 namespace boost
    102 {
    103     template<class F>
    104     struct result_of< boost::fusion::unfused<F> const () >
    105     {
    106         typedef typename boost::fusion::unfused<F>::call_const_0_result type;
    107     };
    108     template<class F>
    109     struct result_of< boost::fusion::unfused<F>() >
    110     {
    111         typedef typename boost::fusion::unfused<F>::call_0_result type;
    112     };
    113 }
    114 
    115162#define BOOST_FUSION_FUNCTIONAL_ADAPTER_UNFUSED_HPP_INCLUDED
    116163#else // defined(BOOST_PP_IS_ITERATING)
    117164////////////////////////////////////////////////////////////////////////////////
     
    122169#define N BOOST_PP_ITERATION()
    123170
    124171        template <class Self, BOOST_PP_ENUM_PARAMS(N,typename T)>
    125         struct result< Self const (BOOST_PP_ENUM_PARAMS(N,T)) >
    126             : boost::result_of< function_c(
     172        struct result< Self (BOOST_PP_ENUM_PARAMS(N,T)) >
     173            : Result< Self (
    127174                BOOST_PP_CAT(fusion::vector,N)< BOOST_PP_ENUM_BINARY_PARAMS(N,
    128175                    typename detail::mref<T,>::type BOOST_PP_INTERCEPT) > & )>
    129176        { };
    130177
    131         template <class Self, BOOST_PP_ENUM_PARAMS(N,typename T)>
    132         struct result< Self(BOOST_PP_ENUM_PARAMS(N,T)) >
    133             : boost::result_of< function(
    134                 BOOST_PP_CAT(fusion::vector,N)< BOOST_PP_ENUM_BINARY_PARAMS(N,
    135                     typename detail::mref<T,>::type BOOST_PP_INTERCEPT) > & )>
    136         { };
    137 
     178        //const interface, non-const arguments
    138179        template <BOOST_PP_ENUM_PARAMS(N,typename T)>
    139         inline typename boost::result_of<function_c(BOOST_PP_CAT(fusion::vector,N)
    140             <BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)> & )>::type
     180        inline typename result< Derived const (BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)) >::type
    141181        operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a)) const
    142182        {
    143183            BOOST_PP_CAT(fusion::vector,N)<
    144184                  BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT) >
    145                 arg(BOOST_PP_ENUM_PARAMS(N,a));
    146             return this->fnc_transformed(arg);
     185                arg(BOOST_PP_ENUM_PARAMS(N,a)); 
     186            return static_cast<Derived const *>(this)->call(arg);
    147187        }
    148188
     189        //non-const interface, non-const arguments
    149190        template <BOOST_PP_ENUM_PARAMS(N,typename T)>
    150         inline typename boost::result_of<function(BOOST_PP_CAT(fusion::vector,N)
    151             <BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)> & )>::type
     191        inline typename result< Derived (BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)) >::type
    152192        operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a))
    153193        {
    154194            BOOST_PP_CAT(fusion::vector,N)<
    155195                  BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT) >
    156196                arg(BOOST_PP_ENUM_PARAMS(N,a));
    157             return this->fnc_transformed(arg);
     197            return static_cast<Derived *>(this)->call(arg);
    158198        }
     199
     200        //const interface, const arguments
     201        template <BOOST_PP_ENUM_PARAMS(N,typename T)>
     202        inline typename result< Derived const (BOOST_PP_ENUM_BINARY_PARAMS(N,T,const & BOOST_PP_INTERCEPT)) >::type
     203        operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const & a)) const
     204        {
     205            BOOST_PP_CAT(fusion::vector,N)<
     206                  BOOST_PP_ENUM_BINARY_PARAMS(N,T,const & BOOST_PP_INTERCEPT) >
     207                arg(BOOST_PP_ENUM_PARAMS(N,a));
     208            return static_cast<Derived const *>(this)->call(arg);
     209        }
     210
     211        //non-const interface, const arguments
     212        template <BOOST_PP_ENUM_PARAMS(N,typename T)>
     213        inline typename result< Derived (BOOST_PP_ENUM_BINARY_PARAMS(N,T,const & BOOST_PP_INTERCEPT)) >::type
     214        operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const & a))
     215        {
     216            BOOST_PP_CAT(fusion::vector,N)<
     217                  BOOST_PP_ENUM_BINARY_PARAMS(N,T,const & BOOST_PP_INTERCEPT) >
     218                arg(BOOST_PP_ENUM_PARAMS(N,a));
     219            return static_cast<Derived *>(this)->call(arg);
     220        }
    159221#undef N
    160222#endif // defined(BOOST_PP_IS_ITERATING)
    161223#endif