I am trying to play with boost::lambda, but I bumped on an error I cannot figure out how to solve.
I have the feeling this is a beginner error, so please excuse my ignorance (and, I have to admit, my laziness for not reading the whole boost lamda documentation too).
It seems that in some cases using boost::bind (or maybe boost::lambda::bind?), is better suited than boost::lambda, but I am not sure if it can be applied here. I would like not having to write a separate function for if cond(arg1) arg2.insert(arg1) ;
, as it would defeat the purpose; it would not be much better than a functor I guess.
I am using boost 1.35 with VC9 at work. The errors are at the cond()
and insert()
calling sites:
"C2664: cannot convert parameter 1 from 'boost::lambda::placeholder1_type"
I replicated the problem with this snippet with g++ on my cygwin.
#include <boost/function.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/if.hpp>
#include <boost/foreach.hpp>
#include <iostream>
#include <set>
void work( boost::function<void(long)> doAction ) {
long results[] = { 2, 5, 4 };
BOOST_FOREACH( long r, results )
doAction( r );
}
bool cond( long r ) { return r % 2 == 0 ; }
int main() {
using namespace boost::lambda;
std::set<long> myResults;
work(
if_then( cond(_1) , boost::ref(myResults).get().insert(_1) ) );
BOOST_FOREACH( long r, myResults )
std::cout << r << "\n";
}
g++ errors:
lambda_test.cpp: In function ‘int main()’:
lambda_test.cpp:21:19: error: cannot convert ‘boost::lambda::placeholder1_type {aka const boost::lambda::lambda_functor<boost::lambda::placeholder<1> >}’ to ‘long int’ for argument ‘1’ to ‘bool cond(long int)’
if_then( cond(_1) , boost::ref(myResults).get().insert(_1) ) );
^
lambda_test.cpp:21:60: error: no matching function for call to ‘std::set<long int>::insert(boost::lambda::placeholder1_type&)’
if_then( cond(_1) , boost::ref(myResults).get().insert(_1) ) );
Any help would be appreciated,
Thanks
You're mixing deferred execution with immediate evaluation:
boost::ref(myResults).get().insert(_1)
Here, boost::ref(myResults)
is not lazy, so .get()
isn't either. The type of boost::ref(myResults).get()
is just std::set<long> &
, and that type's insert
member function doesn't have an overload that takes a Boost Lambda placeholder.
I'm not well-versed in Boost Lambda (anymore) because I've moved to it's successor library, Boost Phoenix. Here's a 1-to-1 translation with fixes: Live On Coliru
#include <boost/phoenix.hpp>
#include <boost/foreach.hpp>
#include <iostream>
#include <set>
template <typename Action>
void work( Action doAction ) {
long results[] = { 2, 5, 4 };
BOOST_FOREACH( long r, results )
doAction( r );
}
bool cond( long r ) { return r % 2 == 0 ; }
int main() {
namespace phx = boost::phoenix;
using namespace phx::placeholders;
std::set<long> myResults;
work(
if_(phx::bind(cond, _1)) [ phx::insert(phx::ref(myResults), _1) ] );
BOOST_FOREACH( long r, myResults )
std::cout << r << "\n";
}
Prints
2
4
I'd suggest to look at Phoenix function adaptation, to avoid the bind expressions: