Bind Vs Lambda?

Tengo una pregunta sobre qué estilo es el preferido: std :: bind Vs lambda en C ++ 0x. Sé que sirven, de alguna manera, diferentes propósitos, pero tomemos un ejemplo de funcionalidad que se cruza.

Usando lambda :

 uniform_int distribution(1, 6); mt19937 engine; // lambda style auto dice = [&]() { return distribution(engine); }; 

Usando bind :

 uniform_int distribution(1, 6); mt19937 engine; // bind style auto dice = bind(distribution, engine); 

¿Cuál deberíamos preferir? ¿por qué? asumiendo situaciones más complejas en comparación con el ejemplo mencionado. es decir, ¿cuáles son las ventajas / desventajas de una sobre la otra?

Como dijiste, bind y lambdas no apuntan exactamente al mismo objective.

Por ejemplo, para usar y componer algoritmos STL, los lambdas son claros ganadores, en mi humilde opinión.

Para ilustrar, recuerdo una respuesta muy divertida, aquí en desbordamiento de stack, donde alguien pidió ideas de números de magia hexagonal (como 0xDEADBEEF, 0xCAFEBABE, 0xDEADDEAD, etc.) y se le dijo que si fuera un progtwigdor de C ++ real, simplemente tendría descargue una lista de palabras en inglés y use un simple trazador de líneas de C ++ 🙂

 #include  #include  #include  #include  #include  #include  #include  int main() { using namespace boost::lambda; std::ifstream ifs("wordsEn.txt"); std::remove_copy_if( std::istream_iterator(ifs), std::istream_iterator(), std::ostream_iterator(std::cout, "\n"), bind(&std::string::size, _1) != 8u || bind( static_cast( &std::string::find_first_not_of ), _1, "abcdef", 0u ) != std::string::npos ); } 

Este fragmento, en C ++ 98 puro, abre el archivo de palabras en inglés, escanea cada palabra e imprime solo las de longitud 8 con ‘a’, ‘b’, ‘c’, ‘d’, ‘e’ o ‘f’ letras.

Ahora, enciende C ++ 0X y lambda:

 #include  #include  #include  #include  #include  int main() { std::ifstream ifs("wordsEn.txt"); std::copy_if( std::istream_iterator(ifs), std::istream_iterator(), std::ostream_iterator(std::cout, "\n"), [](const std::string& s) { return (s.size() == 8 && s.find_first_not_of("abcdef") == std::string::npos); } ); } 

Esto todavía es un poco pesado de leer (principalmente debido al negocio istream_iterator), pero mucho más simple que la versión de enlace 🙂

C ++ 0x lambdas son monomórficas, mientras que bind puede ser polimórfico. No puedes tener algo como

 auto f = [](auto a, auto b) { cout << a << ' ' << b; } f("test", 1.2f); 

ayb deben tener tipos conocidos. Por otro lado, tr1 / boost / phoenix / lambda bind te permite hacer esto:

 struct foo { typedef void result_type; template < typename A, typename B > void operator()(A a, B b) { cout << a << ' ' << b; } }; auto f = bind(foo(), _1, _2); f("test", 1.2f); // will print "test 1.2" 

Tenga en cuenta que los tipos A y B no se arreglan aquí. Solo cuando se usa f, estos dos se deducirán.

La syntax de lamdba de C ++ 0x es más legible que la syntax de enlace. Una vez que ingresas a más de 2 o 3 niveles, tu código se vuelve prácticamente ilegible y difícil de mantener. Preferiría la syntax lambda más intuitiva.

Uno de los beneficios de las lambdas es que son mucho más útiles cuando se necesita agregar un poco de lógica sobre una función existente.

Con bind, se ve obligado a crear una nueva función / método / functor incluso si la lógica solo se necesita en este lugar. Necesitas encontrar un nombre apropiado y puede hacer que el código sea menos comprensible ya que potencialmente te hace dividir la lógica relacionada.

Con lambda, puede agregar la nueva lógica dentro de la lambda (pero no está obligado a hacerlo si tiene sentido crear una nueva llamada).

Creo que es más una cuestión de gusto. Las personas que comprenden rápidamente nuevas tecnologías o que están familiarizadas con la progtwigción funcional probablemente prefieran la syntax lambda, mientras que los progtwigdores más conservadores preferirán definitivamente la vinculación, ya que está más a la par con la syntax tradicional de C ++.

Tal decisión debe tomarse en coordinación con las personas que trabajarán con el código, probablemente a través de una mayoría de votos.

Sin embargo, eso no cambia el hecho de que la syntax lambda es mucho más poderosa y limpia.

C ++ 0x lambdas esencialmente reemplazan bind. No hay nada que puedas vincular que no puedas recrear un envoltorio trivial lambda para lograr lo mismo. std :: tr1 :: bind irá por el camino de std :: bind1st, etc una vez que el soporte de lambda esté muy extendido. Lo cual es bueno, porque por alguna razón la mayoría de los progtwigdores tienen dificultades para resolver su problema.