Boost logo

Boost Users :

Subject: Re: [Boost-users] [Bind] Understanding protect
From: Thomas Heller (thom.heller_at_[hidden])
Date: 2012-03-28 07:04:10


On 03/28/2012 12:41 PM, Robert Jones wrote:
> On Wed, Mar 28, 2012 at 11:13 AM, Thomas Heller
> <thom.heller_at_[hidden]>wrote:
>
>> On 03/28/2012 11:45 AM, Robert Jones wrote:
>>
>>> On Wed, Mar 28, 2012 at 10:04 AM, Thomas Heller
>>> <thom.heller_at_[hidden]>**wrote:
>>>
>>> On 03/28/2012 09:47 AM, Robert Jones wrote:
>>>> On Tue, Mar 27, 2012 at 8:24 PM, Thomas Heller
>>>>> <thom.heller_at_[hidden]>****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>>
>>>>
>>> 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>
>>
>> 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_at_[hidden]
>
http://lists.boost.org/mailman/listinfo.cgi/boost-users


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net