La librarie boost

boost::bind() et boost::function

S'il n'y avait qu'une seule chose à retenir de la librairie boost, ce serait certainement boost::bind.

Cette librairie permet d'utiliser de manière relativement simple des pointeurs de fonction ou des pointeurs sur des methodes.

Mais plutôt qu'un long discours, voici un petit programme :

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

// En general, on utilise un typedef, ca simplifie la vie
typedef boost::function<void (int i)> PFunctor;

// Une methode qui illustre l'utilisation
void callFuntor( PFunctor pf ) {
    int a=1234;
    pf( a );
}


class Test {
    public:        
        void callback1( int a ) {
            std::cout << "Test::callback1(" << a << ")\n";
        }
        void callback2( std::string s, int a ) {
            std::cout << "Test::callback2(" << s << "," << a << ")\n";
        }
        void callback3( int a, std::string s ) {
            std::cout << "Test::callback3(" << a << "," << s << ")\n";
        }
        static void callback4( int a ) {
            std::cout << "Test::callback4(" << a << ")\n";
        }
};

void coucou( std::string s, int i ) {
    std::cout << "coucou s=" << s << " - i=" << i << "\n";
}

int main() {
    // utilisation directe: Les _1 et _2 (...) indiquent a boost::bind comment se debrouiller 
    // avec les arguments. 
    // Toujours se souvenir que l'ordre des arguments doit correspondre au prototype
    // de la fonction appelee
    boost::bind( &coucou, "bla", 123 )();
    boost::bind( &coucou, "blabla", _1)( 456 );
    boost::bind( &coucou, "blablabla", _1 )( 789 );
    boost::bind( &coucou, _1, _2)( "blablablabla", 1011 );
    boost::bind( &coucou, _2, _1)( 1213, "blablablablabla" );
    
    // passage par une variable. En general, on declare des typedefs plus aises a utiliser.
    boost::function<void ()> functor;
    functor = boost::bind( &coucou, "ro", 123 );
    functor();
    boost::function<void (int)> functor2;
    functor2 = boost::bind( &coucou, "roro", _1 );
    functor2(456);
    
    // exemple d'utilisation de _1
    std::vector<int> v;
    v.push_back( 123 ); v.push_back( 456 ); v.push_back( 789 );
    std::for_each( v.begin(), v.end(), boost::bind( &coucou, "blu", _1 ) );
    
    // Exemple d'utilisation avec une classe. Ce qu'il faut remarquer, c'est qu'on
    // passe le pointeur de la classe en premier argument quand il s'agit d'une
    // methode non statique
    Test t;
    // &t = le pointeur en premier
    callFuntor( boost::bind( &Test::callback1, &t, _1 ) );
    // prototype de callback2 => string puis int
    callFuntor( boost::bind( &Test::callback2, &t, "cb2", _1 ) );
    // prototype de callback3 => int puis string
    callFuntor( boost::bind( &Test::callback3, &t, _1, "cb3" ) );
    // callback4 statique, donc pas de this
    callFuntor( boost::bind( &Test::callback4, _1 ) );
    // Utilisation evidemment possible avec une methode d'une autre classe ou bien
    // une fonction, ici, coucou()
    // prototype => string, int
    callFuntor( boost::bind( &coucou, "fin de l'exemple", _1 ) );
    return 0;
}

boost.cc

La sortie écran est la suivante :

$ ./boost
coucou s=bla - i=123
coucou s=blabla - i=456
coucou s=blablabla - i=789
coucou s=blablablabla - i=1011
coucou s=blablablablabla - i=1213
coucou s=ro - i=123
coucou s=roro - i=456
coucou s=blu - i=123
coucou s=blu - i=456
coucou s=blu - i=789
Test::callback1(1234)
Test::callback2(cb2,1234)
Test::callback3(1234,cb3)
Test::callback4(1234)
coucou s=fin de l'exemple - i=1234

Liens

Valid XHTML 1.0!