Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2003-09-17 16:46:05


On Sep 17, 2003, at 4:49 PM, David Abrahams wrote:

> Samuel Krempp <krempp_at_[hidden]> writes:
>
>> simply put, with your suggestion you couldn't tell the difference
>> between
>> assigning to a member or calling a 1-ary member function anymore.
>>
>> bind(&X::member, _1, val) (x); // assigns member, or calls
>> member(val) ?
>
> I don't think it can call member(val). That would have to be:
>
> bind(&X::member, _1)(x)(val)
>
> or
>
> bind(&X::member, x)(val)
>
> wouldn't it?

Nope. Samuel has the right syntax. That's not to say that your
suggestion can't be implemented (I'm sure it can), just that Samuel is
correct in his observation.

>> bind(assign<T>(), bind(&X::member, _1), val) (x);
>>
>> is a bit more verbose, but it could help human reading of long bind
>> expressions, spotting easily where assignments take place. Then
>> again, maybe not, I don't use bind that much.
>
> To me it just looks like gibberish (no offense). How does it work?
> Why should it be neccessary to specify <T>?

<nod> lambda notation is certainly a lot cleaner. The inner bind
returns a unary functional taking a reference or pointer to X, and
returns a reference to member. The outer bind creates a functional
taking the desired reference, and the desired value to assign to it.
The outer functional is still a unary function taking a pointer or
reference to X.

You have to specify T if you want the assign functional to have a
nested result_type of the correct type. This assures that the outer
bind returns an T&. However I've just tested with:

struct assign
{
        template <class T, class U>
        T& operator()(T& t, const U& u) const
                {return t = u;}
};
...
bind(assign(), bind(&X::member, _1), value)(x);

and it works as well. However the resulting functional did not return
a T&. To achieve that one could also:

T& j = bind<T&>(assign(), bind(&X::member, _1), value)(x); // returns
T& now

>> A "quality implementation" of std::bind is expected to compile the
>> code.
>
> <scratch??> I thought you just got through explaining how that's
> impossible because of the exposed result_type?

Well, certainly not /impossible/! ;-)

Yes, the functional returned by mem_fn(M T::*pm) has a type called
result_type that is a const M& (or const M). But that is not
necessarily the type returned when you evaluate the functional. The
trick is talking bind into recognizing the correct return type despite
the presence of the result_type typedef.

-Howard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk