Problem with boost::bind and boost::lambda::bind
I'm a newbie to the boost library so I need some help with the following problem: Take the following code: class EaSde // Abstract class. { ... public: inline virtual double unitDiffusionInverseMap( double x ) const = 0; inline virtual void unitDiffusionInverseMap( Path& path ) const; .... }; void EaSde::unitDiffusionInverseMap( Path& path ) const { std::transform( path.values.begin(), path.values.end(), path.values.begin(), boost::bind<double>( &sde::EaSde::unitDiffusionInverseMap, this, _1 ) ); } This code works fine. However if I use boost::bind::lambda instead of boost::bind I get: 1>Compiling... 1>sdefunctionalmc.cpp 1>c:\develop\nsde\nsde\abstracteasde.hpp(58) : error C2664: 'const boost::lambda::lambda_functor<T> boost::lambda::bind<double,const sde::EaSde*,const boost::lambda::placeholder1_type>(const Arg1 &,const Arg2 &,const Arg3 &)' : cannot convert parameter 1 from 'overloaded-function' to 'const double &' 1> with 1> [ 1> T=boost::lambda::lambda_functor_base<boost::lambda::action<3,boost::lambda::function_action<3>>,boost::tuples::tuple<const double,const sde::EaSde *const ,const boost::lambda::lambda_functor<boost::lambda::placeholder<1>>,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type,boost::lambda::detail::bind_traits<boost::tuples::null_type>::type>>, 1> Arg1=double, 1> Arg2=const sde::EaSde *, 1> Arg3=const boost::lambda::placeholder1_type 1> ] 1> Reason: cannot convert from 'overloaded-function' to 'const double' 1> Context does not allow for disambiguation of overloaded function 1>c:\develop\nsde\nsde\abstracteasde.hpp(58) : error C2780: '_OutIt std::transform(_InIt1,_InIt1,_InIt2,_OutIt,_Fn2)' : expects 5 arguments - 4 provided 1> c:\programmi\microsoft visual studio 8\vc\include\algorithm(797) : see declaration of 'std::transform' Why in this case is boost::bind working and boost::lambda::bind not working? Where can I find more informations on the differences about the two? On a side note I'm wondering if I can expect different performance of the two implementations.... I'm actually moving everything to boost::lambda::bind to 1) avoid the conflict of boost::lambda::_1 and _1 2) have binders that are "lambda ready" if needed Thank you in advance for your reply.
Stefano Peluchetti <pelux <at> ngi.it> writes:
I'm actually moving everything to boost::lambda::bind to 1) avoid the conflict of boost::lambda::_1 and _1 2) have binders that are "lambda ready" if needed
Thank you in advance for your reply.
Note that sometimes boost::bind is a better choice that boost::lambda::bind. 1. boost::bind has better support for smart pointers. struct A { void f() {} }; shared_ptr<A> a; bind(&A::f, _1)(a); // works for boost::bind only 2. boost::bind sometimes can choose correct instance of overloaded function. (probably you got hit by this distinction). struct A { void f() const {} void f() {} }; A a; bind(&A::f, a); // works for boost::bind only 3. boost::bind can accept non-const rvalue if there are not many arguments. I believe last (unreleased) version of boost::lambda::bind can do this as well. void f(int) {} bind(f, _1)(42); // works for boost::bind only My personal experience also shows that boost::bind based code compiles faster. Roman Perepelitsa.
Roman Perepelitsa <roman.perepelitsa <at> db.com> writes:
Stefano Peluchetti <pelux <at> ngi.it> writes:
I'm actually moving everything to boost::lambda::bind to 1) avoid the conflict of boost::lambda::_1 and _1 2) have binders that are "lambda ready" if needed
Thank you in advance for your reply.
Note that sometimes boost::bind is a better choice that boost::lambda::bind.
1. boost::bind has better support for smart pointers.
struct A { void f() {} };
shared_ptr<A> a; bind(&A::f, _1)(a); // works for boost::bind only
2. boost::bind sometimes can choose correct instance of overloaded function. (probably you got hit by this distinction).
struct A { void f() const {} void f() {} };
A a; bind(&A::f, a); // works for boost::bind only
3. boost::bind can accept non-const rvalue if there are not many arguments. I believe last (unreleased) version of boost::lambda::bind can do this as well.
void f(int) {}
bind(f, _1)(42); // works for boost::bind only
My personal experience also shows that boost::bind based code compiles faster.
Roman Perepelitsa.
Very interesting information, thank you. Is there any documentation about these details ? I couldn't find anything like that in the boost lambda library documentation. I noticed that boost::bind code usually compiles faster too. But I'm working an a numerical simulation library and I have to compose functions together a lot of times. That's where lambda is very handy. Also I can't still understand *why* only the boost::bind binder works in the three examples you gave. What is the technical reason behind these results? Is it really necessary to study the whole boost::lambda library from source code to figure it out? Best Regards
Stefano Peluchetti <pelux <at> ngi.it> writes:
Very interesting information, thank you. Is there any documentation about these details ? I couldn't find anything like that in the boost lambda library documentation.
I noticed that boost::bind code usually compiles faster too. But I'm working an a numerical simulation library and I have to compose functions together a lot of times. That's where lambda is very handy.
Also I can't still understand *why* only the boost::bind binder works in the three examples you gave. What is the technical reason behind these results? Is it really necessary to study the whole boost::lambda library from source code to figure it out?
Best Regards
AFAIK, there are no reasons for not supporting this stuff in lambda bind, except one -- it requires time for implementation. Some day we'll have both of two worlds -- phoenix 2. It should unite boost bind, boost lambda and phoenix. I believe no one is seriously interested in improving boost lambda at the moment because this code gonna become obsolete soon. Roman Perepelitsa.
Stefano Peluchetti wrote:
I'm a newbie to the boost library so I need some help with the following problem: Take the following code:
class EaSde // Abstract class. { ... public: inline virtual double unitDiffusionInverseMap( double x ) const = 0; inline virtual void unitDiffusionInverseMap( Path& path ) const; .... };
void EaSde::unitDiffusionInverseMap( Path& path ) const { std::transform( path.values.begin(), path.values.end(), path.values.begin(), boost::bind<double>( &sde::EaSde::unitDiffusionInverseMap, this, _1 ) ); }
This code works fine. However if I use boost::bind::lambda instead of boost::bind I get:
... Bind libraries in general have trouble with overloaded functions; this is a limitation of C++. boost::bind is slightly better than lambda::bind in such cases. No, there is no list of the differences between boost::bind and lambda::bind. FWIW, I wasn't aware of the above difference in behavior, so the list wouldn't have had it anyway. :-)
participants (3)
-
Peter Dimov
-
Roman Perepelitsa
-
Stefano Peluchetti