diff --git a/example/cookbook/do_the_bind.cpp b/example/cookbook/do_the_bind.cpp index 33772383..ac5baee4 100644 --- a/example/cookbook/do_the_bind.cpp +++ b/example/cookbook/do_the_bind.cpp @@ -22,23 +22,29 @@ form. ==============================================================================*/ + #include -#include -#include +#include #include #include -#include #include -#include +#include #include #include +#include +#include + +#include +#include #include #include #include #include +#include +#include #include #include @@ -105,6 +111,7 @@ namespace impl // returned by bind template class fused_bound_function { + // Transform arguments to be held by value typedef typename traits::deduce_sequence::type bound_args; bound_args fsq_bind_args; @@ -144,19 +151,40 @@ namespace impl }; + // Find the number of placeholders in use + struct n_placeholders + { + struct fold_op + { + template struct result; + template struct result< S(A &,B &) > + : mpl::max { }; + }; + struct filter_pred + { + template struct apply : is_placeholder { }; + }; + + template + struct apply + : mpl::next< typename result_of::fold< + fusion::filter_view, mpl::int_<-1>, fold_op + >::type>::type + { }; + }; + // Fused implementation of the 'bind' function struct fused_binder { template struct result; - template + template ::value> 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 > type; + typedef boost::forward_adapter,!Placeholders>,Placeholders> type; }; template @@ -168,14 +196,16 @@ namespace impl inline typename result_impl< BindArgs >::type operator()(BindArgs & bind_args) const { - return typename result< void(BindArgs) >::type(bind_args); + return typename result< void(BindArgs) >::type( + fusion::unfused< fused_bound_function, + ! n_placeholders::apply::value >(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 + // The binder's unfused type. We use lightweght_forward_adapter 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 binder; + typedef boost::lightweight_forward_adapter< fusion::unfused > binder; } // Placeholder globals @@ -225,10 +255,11 @@ int main() 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,"The answer is",_1_)(12) == 2); errors += !( bind(f,_1_,ref(value))("Really?") == 2); errors += !( bind(f,_1_,_2_)("Dunno. If there is an answer, it's",value) == 2);