Inconsistency between boost::bind and boost::lambda::bind

Hello everybody, I've started to use the functional programming facilities offered by boost, and they're really impressive. To begin with, I've started using both; I've seen however, that when I #include both <boost/bind.hpp> and <boost/lambda/bind.hpp> I must use full namespace names to address lambda placeholders. In other words, instead of writing for_each(container.begin(), container.end(), cout << _1 << constant('\n')); I've to write for_each(container.begin(), container.end(), cout << boost::lambda::_1 << boost::lambda::constant('\n')); also if I've written a using boost::lambda declaration; I know, I can simplify this using a namespace alias, but I was trying to keep the code less clobber as I can, because it has to be used for teaching/example purposes. So, my first question would be: where could I find an exhaustive comparison between these two facilities? And, is there any indication on what to prefer, also related to future development and/or inclusion in C++ standards (If I remember well, boost::lambda has been proposed in tr1?) The second question points at a small inconsistency that I believe I've found while doing some experiments: boost::bind and boost::lambda::bind offer similar construct, but the former works while the latter fails in the example included below. I'm using boost_1_33_1, with g++ -v (provided below) Target: i586-mandriva-linux-gnu Configured with: ../configure --prefix=/usr --libexecdir=/usr/lib --with-slibdir=/lib --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --enable-languages=c,c++,ada,f95,objc,java --host=i586-mandriva-linux-gnu --with-system-zlib --enable-long-long --enable-__cxa_atexit --enable-clocale=gnu --disable-libunwind-exceptions --enable-java-awt=gtk --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --enable-gtk-cairo --disable-libjava-multilib Thread model: posix gcc version 4.0.1 (4.0.1-5mdk for Mandriva Linux release 2006.0) The situation is the following: if I try to create a nullary lamnda function with boost::lambda::bind() like this: generate_n(inserter(v, v.begin()), 10, boost::lambda::bind<Slave*>( boost::lambda::new_ptr<Slave>(),*this) ); the compiler fails to compile: it tries to pass the this pointer as a const reference somehow, and then it fails claiming that a Slave(const Master& m) cannot be found; If I try to add one, it fails with a similar error. If I substitute the boost::lambda::bind() with a boost::bind(), it compiles & works perfectly. Thanks for the attention, -Gerardo Lamastra ------------------------------------------------------------------------- #include <set> #include <algorithm> #include <iterator> #include <iostream> #include <boost/lambda/lambda.hpp> #include <boost/lambda/construct.hpp> #include <boost/lambda/bind.hpp> #include <boost/bind.hpp> using namespace std; using namespace boost::lambda; class Master; struct Slave { static int globalId; Master& master; int id; Slave(Master& m) : master(m), id(++globalId) {}; }; int Slave::globalId = 0; class Master { struct Builder { typedef Slave* result_type; Slave* operator()(Master& master) { return new Slave(master); }; }; static Slave* build(Master& master) { return new Slave(master); } public: void print(set<Slave*> s) { for_each(s.begin(), s.end(), (cout << constant("S: ") << (boost::lambda::_1) ->* &Slave::id) << '\n' ); } void f1() { /* This is the most trivial thing I've tried, but I need to write builder explicitely; */ set<Slave*> v; generate_n(inserter(v, v.begin()), 10, boost::bind(Builder(),*this) ); print(v); } void f2() { /* A more compact, but substantially identical form */ set<Slave*> v; generate_n(inserter(v, v.begin()), 10, boost::bind(&Master::build,*this) ); print(v); } void f3() { /* Does not work; it seems that the object passed to the compiler is a const Master& instead of just a Master&, it is like that the boost::lambda::bind() adds a const where that is not required... I tried to substitute the Master& in the Slave() constructor with a const Master& but it does not work either */ /* set<Slave*> v; generate_n(inserter(v, v.begin()), 10, boost::lambda::bind(&Master::build,*this) ); print(v); */ } void f4() { /* The same issue applies here... * This has been my original experiment, which * motivated all this trouble... */ /* set<Slave*> v; generate_n(inserter(v, v.begin()), 10, boost::lambda::bind<Slave*>( boost::lambda::new_ptr<Slave>(),*this) ); print(v); */ } void f5() { /* A work-around that I come up with, * mixing boost::bind && boost::lambda::new_ptr */ set <Slave*> v; generate_n(inserter(v, v.begin()), 10, boost::bind<Slave*>(boost::lambda::new_ptr<Slave>(),*this) ); print(v); } }; int main() { Master m; cout << "F1: " << endl; m.f1(); cout << "F2: " << endl; m.f2(); cout << "F5: " << endl; m.f5(); } -------------------------------------------------------------------- CONFIDENTIALITY NOTICE This message and its attachments are addressed solely to the persons above and may contain confidential information. If you have received the message in error, be informed that any use of the content hereof is prohibited. Please return it immediately to the sender and delete the message. Should you have any questions, please contact us by replying to webmaster@telecomitalia.it. Thank you www.telecomitalia.it --------------------------------------------------------------------

If you must include both, I'd suggest using the namespace alias (as I've commonly seen it: bll = boost::lambda) While I don't know of an exhaustive comparison, I do believe that boost::bind has better support for smart pointers. As to the const/non-const ref problem, try using boost::ref. HTH, Pablo Aguilar Gerardo Lamastra wrote:
Hello everybody,
I've started to use the functional programming facilities offered by boost, and they're really impressive.
To begin with, I've started using both; I've seen however, that when I #include both and I must use full namespace names to address lambda placeholders. In other words, instead of writing
<snip code>
also if I've written a using boost::lambda declaration; I know,
I can simplify this using a namespace alias, but I was trying to keep the code less clobber as I can, because it has to be used for teaching/example purposes. So, my first question would be: where could I find an exhaustive comparison between these two facilities? And, is there any indication on what to prefer, also related to future development and/or inclusion in C++ standards (If I remember well, boost::lambda has been proposed in tr1?)
The second question points at a small inconsistency that I believe I've found while doing some experiments: boost::bind and boost::lambda::bind offer similar construct, but the former works while the latter fails in the example included below.
The situation is the following: if I try to create a nullary lamnda function with boost::lambda::bind() like this:
generate_n(inserter(v, v.begin()), 10, boost::lambda::bind( boost::lambda::new_ptr(),*this) );
the compiler fails to compile: it tries to pass the this pointer as a const reference somehow, and then it fails claiming that a Slave(const Master& m) cannot be found; If I try to add one, it fails with a similar error.
If I substitute the boost::lambda::bind() with a boost::bind(), it compiles & works perfectly.
Thanks for the attention, -Gerardo Lamastra
<snip code and legal notice>

Gerardo Lamastra wrote:
So, my first question would be: where could I find an exhaustive comparison between these two facilities? And, is there any indication on what to prefer, also related to future development and/or inclusion in C++ standards (If I remember well, boost::lambda has been proposed in tr1?)
Nobody has written an exhaustive comparison between boost::bind and lambda::bind, but the general rule is to use lambda::bind if you use Lambda, boost::bind otherwise. :-) TR1 contains a 'bind' that is a superset of boost::bind. Both boost::bind and boost::lambda::bind are reasonable approximations of std::tr1::bind.
The situation is the following: if I try to create a nullary lamnda function with boost::lambda::bind() like this:
generate_n(inserter(v, v.begin()), 10, boost::lambda::bind<Slave*>( boost::lambda::new_ptr<Slave>(),*this) );
the compiler fails to compile: it tries to pass the this pointer as a const reference somehow, and then it fails claiming that a Slave(const Master& m) cannot be found; If I try to add one, it fails with a similar error.
If I substitute the boost::lambda::bind() with a boost::bind(), it compiles & works perfectly.
Your code seems wrong. Remember that bind makes a copy of its arguments, '*this' in this case. So when you construct a new Slave, its reference is initialized to this internal copy of *this. The function object then disappears and the result is a dangling reference. Use boost::ref(*this). Now, if you are interested in why Lambda doesn't accept the code whereas Bind does: Lambda always makes these internal copies const. boost::bind propagates the const-ness of the function object to its members. In this case the function object is non-const and so is the internal copy of *this.
participants (3)
-
Gerardo Lamastra
-
Pablo Aguilar
-
Peter Dimov