Boost logo

Boost Users :

From: Gerardo Lamastra (gerardo.lamastra_at_[hidden])
Date: 2006-05-08 09:35:29


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_at_telecomitalia.it.

        Thank you

                                        www.telecomitalia.it

--------------------------------------------------------------------



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net