Boost logo

Boost Users :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2003-11-21 09:46:55


Allen Bierbaum wrote:
> Hello all.
>
> I am having trouble with the boost lambda library. I am convinced
> that my troubles come from some little thing I am overlooking, but
> for the life of me I can't seem to find the problem. I have been
> looking at it for the entire afternoon with no solution in sight.
>
> I have included some sample code below showing the basic idea of what
> I am trying to accomplish. Can anyone provide me with a working
> solution?
>
> The summary is:
> - I have a vector of shared_ptr's to a class A
> - That class has a method that returns a value I would like to test
> for in a find_if call

[...]

> Can anyone tell me how I can call a method from a lamda method
> iterating over a sequence of shared_ptrs? And then how do I have
> this method also call another method?

The short answer is that you can't, at least with the current
implementation.

There are three possible ways to call a member function with Lambda:

    (bl::_1 ->* &Foo::bar )(foo_ptr);
    bl::bind(&Foo::bar, *bl::_1)(foo_ptr);
    bl::bind(&Foo::bar, bl::_1)(foo_ptr);

The first alternative doesn't work since shared_ptr does not have
operator->*.

The second alternative doesn't work since Lambda doesn't support *_1 for
shared_ptr.

The third alternative doesn't work since it is not supported by Lambda
(probably by design), although it is supported by Bind, and may be supported
by a future version of Lambda.

The Bind equivalent is:

    boost::bind(&Foo::bar, _1)(foo_ptr);

and it does work.

Your complete example can be written with Bind as:

    std::find_if( foos.begin(), foos.end(),
        boost::bind(std::equal_to<int>(),
            boost::bind(&A::getInt,
                boost::bind(&Foo::bar, _1)
            ),
            find_int
        )
    );

It is clumsier since the more limited Bind vocabulary forces the use of
std::equal_to instead of simply composing an expression using operator==.
You need to make A::getInt() const, though. Non-const member functions can
be invoked on rvalues, but Bind isn't sophisticated enough to realize that.
I suspect that in your real code getInt is const.

All that said, you might want to rethink whether you want to use Lambda or
Bind in this way here. A helper function would simplify the example
considerably:

    bool has_guid(shared_ptr<Foo> const & p, int guid)
    {
        return p->bar().getInt() == guid;
    }

    std::find_if( first, last, bind( has_guid, _1, child_guid) );

HTH


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