
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 --------------------------------------------------------------------