A Coder’s Corner

Blog de tecnologia y programación

Boost.Function + Boost.Bind

Posted by gfaraj on May 3, 2007

La combinación de Boost.Function y Boost.Bind es la que más utilizo de Boost. Son librerias que encapsulan funciones y las dos se usan de la par. La primera guarda una funcion generica de cierto prototipo, la segunda se usa de adaptador que actua como una funcion. Empecemos con un ejemplo de Boost.Function:

void foo();

int main()
{
    // queremos guardar una funcion con resultado void y sin parametros
    boost::function<void ()> func = foo;
    func();
}

Ahi pueden ver un ejemplo sencillo de como usar boost::function, aunque poco util en este ejemplo. Lo interesante que veremos adelante es que tambien podemos guardar funciones miembros a la par de funciones normales, algo que no se puede hacer con simples punteros a las funciones. Aqui es donde entra boost::bind.

void foo();

class Bar
{
public:
    void baz();
};

int main()
{
    boost::function<void ()> func = foo;
    func();

    Bar bar;
    func = boost::bind(&Bar::baz, &bar);
    func();
}

En el ejemplo pueden ver que se puede usar el mismo objeto para guardar una funcion normal y una funcion miembro. Esto es muy util para cuando se ocupan “callbacks.” De costumbre, las APIs hechas en C cuando ocupan un callback se tiene que pasar un puntero a una funcion normal y ademas proveer un campo denominado “user data” que por lo general es un void*. Esto puede ser inseguro y es muy tedioso. Aqui vemos que no es nada del otro mundo usar los objetos de Boost. Para finalizar voy a poner codigo ilustrando otras aplicaciones de estas clases.

void foo(int x, bool y);

class Bar
{
public:
    void baz();
};

int main()
{
    // llamar una funcion de cada objeto en un vector
    std::vector<Bar> v1(10);
    std::for_each(v1.begin(), v1.end(), boost::bind(&Bar::baz, _1));

    bool r = true;
    boost::bind(foo, 10, _1)(r);      // foo(10, r);

    int s = 30;
    boost::bind(foo, _1, false)(s);   // foo(s, false);
    boost::bind(foo, _1, _2)(s, r);   // foo(s, r);
}

El _1 y el _2 son “placeholders” que ocupan el espacio del primer y el segundo parametro de la funcion, respectivamente. Espero que les haya gustado, y si les gusto talvez les guste Boost.Signal que es una libreria mas especificamente para manejar “callbacks” ya que un objeto puede almacenar varias funciones, no solo una. Igual, funciona bien a la par de Boost.Function y Boost.Bind.

3 Responses to “Boost.Function + Boost.Bind”

  1. KeyBreaker said

    Podrias explicar la utilidad de esto, poniendo un ejemplo de como se haria con STL o algun otro metodo al que el uso de function-bind supere?
    Tengo un codigo con threads y funtion-bind y me resulta indescriptible.

  2. gfaraj said

    Hola KeyBreaker,

    Pues por los momentos no hay nada en la libreria estandar que se le acerque en cuanto a funcionalidad a Boost.Function y Boost.Bind. De hecho, en la nueva version del estandar, se incorporaran éstos.
    Lo importante notar acerca de Boost.Function es que permite almacenar cualquier funcion/objeto que satisfaga el tipo pasado. Por ejemplo, boost::function puede almacenar cualquier objeto que, usando el operador(), se le pase un bool y retorne un int.


    int f1(bool);
    int f2(bool, int);
    int f3(bool, char, std::string);
    struct f4
    {
    int operator()(bool);
    };
    struct o
    {
    int f5(bool);
    };
    boost::function f;
    f = &f1;
    f(true); // f1(true);
    f = boost::bind(&f2, _1, 10);
    f(true); // f2(true, 10);
    f = boost::bind(&f3, _1, 10, "hola");
    f(true); // f2(true, 10, "hola");
    f = f4();
    f(true); // f4()(true);
    o o1;
    f = boost::bind(&o::f4, &o1, _1);
    f(true); // o1.f4(true);

    Lo mas cercano seria std::bind1st, std::bind2nd, y std::mem_fun. Son extremadamente limitados, y es por eso que seran reemplazados en la proxima edicion del estandar.

    El codigo con threads del que hablas es Boost.Thread? Esa usa una boost::function para la funcion del hilo.


    void f(int x);
    boost::thread t(boost::bind(&f, 10)); // empieza el thread, y llama f(10)

    Si ocupas mas ejemplos, me avisas.
    Ahi disculpa el formato del codigo, WordPress es malisimo para formatear codigo.

    • Javier said

      Muchas Gracias!! Eres el primero que veo que explica esto de manera inteligible.

      Boost es increíblemente potente!! Por cierto, para el for_each, yo utilizaría el de boost cambien, es mas esquemático.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: