
Hi All I'd appreciate some helpful words about Boost.Bind protect, 'cos I'm not quite understanding it! I thought its purpose was allow binding, but not evaluating, of a function object. So that this should work. #include <iostream> #include <boost/bind.hpp> #include <boost/bind/protect.hpp> void f( int i ) { std::cout << i << std::endl; } template <typename NullaryCallable> void g( const NullaryCallable & callable ) { callable( ); } int main( ) { g( protect( bind( f, _1 ) )( 1 ) ); } But it doesn't, and instead thinks I'm calling g() with the return type of f(), just as if I'd not used protect at all. Is it possible to have bind generate a fully bound, nullary callable object? TIA, - Rob.

I thought its purpose was allow binding, but not evaluating, of a function object.
...when passed to bind() as a not first argument.
Sure, protect doesn't do anything here.
Is it possible to have bind generate a fully bound, nullary callable object?
bind(f, 1);

On Tue, Mar 27, 2012 at 3:46 PM, Igor R <boost.lists@gmail.com> wrote:
Yeah, but that doesn't quite fit the bill! Ultimately I'm doing this for each member of a range, via std algorithm, so I need to bind a unary argument to produce a nullary function object, which I can then pass to an evaluation context, ie my g( ) function. If I've generated the function object with bind and placeholder(s), it seems there's no way to prevent the binding of the last placeholder from triggering evaluation, when what I require is an unevaluated nullary function object. Thx, Rob.

On Mar 27, 2012, at 2:13 PM, Robert Jones wrote:
Hmm, works for me, IIUC: #include <boost/bind.hpp> #include <iostream> template<typename F> void g(F const &f) { f(); } void f(int x) { std::cout << "x is " << x << std::endl; } int main() { for(int i=0; i<7; ++i) g(boost::bind(f,i)); return 0; }

On 03/27/2012 10:17 PM, Robert Jones wrote:
You might also want to consider phoenix::lambda, it is like protect, but slightly more powerful. your example would then read: #include <boost/phoenix.hpp> int main( ) { std::vector<int> v; v += 0,1,2,3,4,5,6; using boost::phoenix::bind; using boost::phoenix::lambda; using boost::phoenix::placeholders::_1; using boost::phoenix::local_names::_1; for_each( v.begin( ), v.end( ), bind(g, lambda(_a = _1)[bind(f, _a)])); return 0; }

On Wed, Mar 28, 2012 at 10:04 AM, Thomas Heller <thom.heller@googlemail.com>wrote:
Hi Tom Thanks for the time you've spent on this- much appreciated. I can see where you're going with this approach, however if I've understood it correctly it sidesteps the hard bit in that the function g() now takes a unary callable and a value. My key constraint here is that g() MUST take a nullary callable object, and hence the bind machinations MUST produce a fully bound, unevaluated, nullary callable object. I feel like I'm banging-on a bit here - sorry! Thx, Rob.

On Wed, Mar 28, 2012 at 11:13 AM, Thomas Heller <thom.heller@googlemail.com>wrote:
So, looking to generalise and clean-up a bit,... * is there a compelling reason why invoke declares a local variable, rather than invoking g directly? * would it be reasonable to pass g as a ctor parameter to g_trampoline? * could g_trampoline reasonably be templated on return type (currently void)? This seems to me to be a pretty common use-case, possibly also for two and three argument versions of f(). Is there a general facility here that's worth formalising? Maybe that's already been subsumed by your phoenix work? Just thinking out-loud. Thx, Rob. variable

On 03/28/2012 12:41 PM, Robert Jones wrote: > On Wed, Mar 28, 2012 at 11:13 AM, Thomas Heller > <thom.heller@googlemail.com>wrote: > >> On 03/28/2012 11:45 AM, Robert Jones wrote: >> >>> On Wed, Mar 28, 2012 at 10:04 AM, Thomas Heller >>> <thom.heller@googlemail.com>**wrote: >>> >>> On 03/28/2012 09:47 AM, Robert Jones wrote: >>>> On Tue, Mar 27, 2012 at 8:24 PM, Thomas Heller >>>>> <thom.heller@googlemail.com>****wrote: >>>>> >>>>> >>>>> You might also want to consider phoenix::lambda, it is like protect, >>>>> but >>>>> >>>>>> slightly more powerful. >>>>>> your example would then read: >>>>>> #include<boost/phoenix.hpp> >>>>>> >>>>>> int main( ) >>>>>> { >>>>>> std::vector<int> v; >>>>>> v += 0,1,2,3,4,5,6; >>>>>> using boost::phoenix::bind; >>>>>> using boost::phoenix::lambda; >>>>>> using boost::phoenix::placeholders::******_1; >>>>>> using boost::phoenix::local_names::_******1; >>>>>> >>>>>> >>>>>> >>>>>> for_each( v.begin( ), v.end( ), >>>>>> bind(g, lambda(_a = _1)[bind(f, _a)])); >>>>>> >>>>>> return 0; >>>>>> } >>>>>> >>>>>> >>>>>> Please don't remind me! I'd love to, but I'm stuck in the antediluvian >>>>>> >>>>> days >>>>> of 1.37! >>>>> >>>>> - Rob. >>>>> >>>>> Ouch. In that case, protect should work just fine. >>>> Here is a complete and working example: >>>> https://gist.github.com/****2224915<https://gist.github.com/**2224915>< >>>> https://gist.github.**com/2224915<https://gist.github.com/2224915>> >>>> >>> Hi Tom >>> >>> Thanks for the time you've spent on this- much appreciated. >>> >>> I can see where you're going with this approach, however if I've >>> understood >>> it correctly it >>> sidesteps the hard bit in that the function g() now takes a unary callable >>> and a value. My key >>> constraint here is that g() MUST take a nullary callable object, and hence >>> the bind machinations >>> MUST produce a fully bound, unevaluated, nullary callable object. >>> >>> I feel like I'm banging-on a bit here - sorry! >>> >> Ha, no problem, I enjoy solving such problems :) >> After jumping through all kinds of different hoops, I updated the gist: >> https://gist.github.com/**2224918<https://gist.github.com/2224918> >> >> I hope this fits your usecase better :) The original function is >> unchanged, I just added the trampoline to rebind the bound functor. Well, >> not the most elegant solution, but might work. >> >> Now that's a solution! > So, looking to generalise and clean-up a bit,... > * is there a compelling reason why invoke declares a local variable, rather > than invoking g directly? The reason is because the compiler needs to know which g function needs to be instantiated in order to take its adress. The alternative of making a local function pointer variable would be to cast the function into the correct type, which i never get right on the first try ;) > * would it be reasonable to pass g as a ctor parameter to g_trampoline? In order to do that, you need to know the exact type of the nullary function, which is not really possible at the time when you bind g_trampoline, same reason as above (you don't want to manually get the type of those bind and protect beasts). If g wasn't a template, it could be certainly done. > * could g_trampoline reasonably be templated on return type (currently > void)? Yes, this is certainly possible. I omitted that for simplicity. > > This seems to me to be a pretty common use-case, possibly also for two and > three argument versions > of f(). Is there a general facility here that's worth formalising? Maybe > that's already been subsumed by > your phoenix work? Just thinking out-loud. Using g_trampoline for more than just a single argument is trivial. Just add the appropriate operator() overloads and you are done. What i demonstrated using plain boost.bind facilities is more or less a poor resemblence of what can be done with phoenix::lambda. phoenix::lambda can capture local variables (stored inside the result phoenix expression object), in our case we want to capture the first argument which is passed when the phoenix expression is evaluated first. when this lambda is called again, the _a placeholder gets substituted with the content of the local variable and the bound f is called with that parameter. > Thx, Rob. > variable > > _______________________________________________ > Boost-users mailing list > Boost-users@lists.boost.org > http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (4)
-
Gordon Woodhull
-
Igor R
-
Robert Jones
-
Thomas Heller