2010-06-21 8 views
13

Echo un vistazo a las bibliotecas de Boost que se incluyeron en el Informe técnico 1 de C++ e intento entender qué hace cada una.¿De qué sirve usar boost :: mem_fn si tenemos boost :: bind?

Acabo de ejecutar un ejemplo para boost::mem_fn y ahora me pregunto cuál es el punto de usarlo en lugar del mejor boost::bind. Por lo que yo entiendo, ambos devuelven un objeto de función que apunta a una función miembro. Encuentro mem_fn tan limitado que no puedo encontrar un escenario donde usarlo sería mejor que bind.

¿Echo de menos algo? ¿Hay algún caso en el que bind no pueda reemplazar mem_fn?

Respuesta

7

mem_fn es mucho más pequeño que bind, por lo que si sólo se necesita la funcionalidad de mem_fn Es mucho menos código para tirar en.

2

Bueno, vincular depende de mem_fun así que ahí lo tienes. Cómo y por qué lo dejo para que lo descubras, aunque, aunque interesante, no tengo tiempo para investigar en este momento (el enlace es complicado).

1

boost::lambda tiene una superposición de funcionalidad similar a las dos que mencionaste. Creo que todos evolucionaron con una intención similar, casi al mismo tiempo, con diferentes enfoques, lo que generó confusión y problemas de incompatibilidad. Sería bueno si todos se fusionaran bajo un paraguas lambda.

Por lo tanto, no, no existe un diseño global que requiera la coexistencia de ambas bibliotecas.

+3

Lo curioso es que tanto 'bind' como' mem_fn' han llegado al Informe técnico 1 de C++, y se supone que el comité de C++ es bastante estricto. ¿No se dieron cuenta de que estamos duplicando funcionalidades? –

5

mem_fn es más pequeño y más rápido que bind. Pruebe el siguiente programa con su compilador favorito y compare:

  1. El tamaño del ejecutable resultante y
  2. El número de segundos reportados como se gasta.

Es posible comparar el rendimiento de bind frente mem_fn cambiando el 1 a 0 en la línea #if.

#include <iostream> 
#include <functional> 
#include <chrono> 

struct Foo 
{ 
    void bar() {} 
}; 

int main(int argc, const char * argv[]) 
{ 
#if 1 
    auto bound = std::bind(&Foo::bar, std::placeholders::_1); 
#else 
    auto bound = std::mem_fn(&Foo::bar); 
#endif 
    Foo foo; 
    auto start = std::chrono::high_resolution_clock::now(); 
    for(size_t i = 0; i < 100000000; ++i) 
    { 
     bound(foo); 
    } 
    auto end = std::chrono::high_resolution_clock::now(); 
    auto delta = std::chrono::duration_cast< std::chrono::duration<double>>(end - start); 
    std::cout << "seconds = " << delta.count() << std::endl; 
    return 0; 
} 

Los resultados pueden variar, pero en mi sistema actual de la versión mem_fn del ejecutable es de 220 bytes más pequeña y corre alrededor de dos veces más rápido que la versión bind.

Y como bonus, mem_fn no requiere que recuerde añadir std::placeholders::_1 como bind does (so pena de un error del compilador con plantilla oscura).

Por lo tanto, prefiera mem_fn cuando pueda.

+0

+1 para el código de referencia. – felipou

+0

Creo que las optimizaciones de GCC harán que la velocidad sea más o menos la misma para ambos. Acabo de probar usando "-O2" con su código (e imprimiendo algo en la función "barra", de lo contrario el optimizador verá que no está haciendo nada). A veces, la versión de "enlace" es incluso más rápida. – felipou

+0

Debería agregar algo como 'static vollatile int i; i; 'en el cuerpo de la" barra ", de lo contrario el compilador puede optimizar la llamada a la función vacía (lo que realmente sucede en mi caso con' bind 'y 'mem_fn'). Los resultados de referencia para 'bind' y' mem_fn' son iguales en mi PC (* gcc 4.9 *, '-O3'),' mem_fn' no es más rápido que 'bind'. –

Cuestiones relacionadas