problems with C++ boost lambda and ==-operator

381 views Asked by At

There is:

template<typename T>
bool any(::Ref<Iterator<T> > i, boost::function<bool(T)> pred) {
    // ...
}

And:

template<typename T> struct Ref {
     // ...
};

template<typename T> struct Iterator {
     // ...
};

Then I have this call (which errors):

int forworm = 42;
bool x = any<CWorm*>(worms(), (_1 ->* &CWorm::getID) == forworm)

And worms() returns a Ref<Iterator<CWorm*> Ref> and there is int CWorm::getID(); (which is a member function).

This fails with a very lengthy error about invalid operands to binary expression. Part of it:

/usr/local/include/boost/lambda/detail/operator_lambda_func_base.hpp:222:1:{222:1-222:63}{222:1-222:63}: error: invalid operands to binary expression ('typename lambda_functor_base >, tuple >, int (CWorm::*const)() const, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type> >::sig >::type' (aka 'member_pointer_caller') and 'int') [3]

Why?

How can I fix it?

If I do it somewhat more verbose, i.e. not via lambdas but I declare another function manually and use boost::bind, it works. I.e. like this:

static bool _wormIdEqual(CWorm* w, int wormId) {
    return w->getID() == wormId;
}

any<CWorm*>(worms(), boost::bind(_wormIdEqual, _1, forworm)))
2

There are 2 answers

10
Aaron McDaid On BEST ANSWER

You should be able to do this:

#include <boost/lambda/bind.hpp>

using boost::lambda::bind;
bool x = any<CWorm*>(worms(), bind(&CWorm::getID, _1) == forworm);

The boost::lambda::bind(&CWorm::getID, _1) behaves just as you hoped (_1 ->* &CWorm::getID) would, and can (lazily) compare for equality against forworm. So it's still very much a lambda function.

2
Karel Petranek On

Quote from Boost.Lambda documentation:

Lambda expressions containing function calls, control structures, casts etc. require special syntactic constructs. Most importantly, function calls need to be wrapped inside a bind function. As an example, consider the lambda expression

You are trying to invoke a function in your code so you must use bind() to actually defer the calling of the function. Moreover, it's also cleaner to delay the variable/constant forworm:

int forworm = 42;
bool x = any<CWorm*>(worms(), bind(&CWorm::getID, _1) == var(forworm));

This answer is an enhancement of @Aaron McDaid's answer, it just got too long for a comment.