Bind Vs Lambda?

J’ai une question concernant le style préféré: std :: bind Vs lambda en C ++ 0x. Je sais qu’ils servent à des fins différentes mais prenons un exemple de fonctionnalité croisée.

En utilisant lambda :

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

En utilisant bind :

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

Lequel devrions-nous préférer? Pourquoi? en supposant des situations plus complexes par rapport à l’exemple mentionné. C’est-à-dire quels sont les avantages / inconvénients de l’un par rapport à l’autre?

Comme vous l’avez dit, bind et lambdas ne visent pas exactement le même objective.

Par exemple, pour utiliser et composer des algorithmes STL, les lambdas sont clairement gagnants, à mon humble avis.

Pour illustrer, je me souviens d’une réponse vraiment amusante, ici sur le débordement de stack, où quelqu’un a demandé des idées de nombres magiques hexadécimaux (comme 0xDEADBEEF, 0xCAFEBABE, 0xDEADDEAD etc.). télécharger une liste de mots anglais et utiliser un simple traceur 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::ssortingng::size, _1) != 8u || bind( static_cast( &std::ssortingng::find_first_not_of ), _1, "abcdef", 0u ) != std::ssortingng::npos ); } 

Cet extrait, en C ++ 98, ouvre le fichier de mots anglais, parsing chaque mot et n’imprime que ceux de longueur 8 avec ‘a’, ‘b’, ‘c’, ‘d’, ‘e’ ou ‘f’ des lettres.

Activez maintenant C ++ 0X et 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::ssortingng& s) { return (s.size() == 8 && s.find_first_not_of("abcdef") == std::ssortingng::npos); } ); } 

C’est encore un peu lourd à lire (principalement à cause de l’activité istream_iterator), mais beaucoup plus simple que la version bind 🙂

C ++ 0x lambdas sont monomorphes, alors que bind peuvent être polymorphes. Vous ne pouvez pas avoir quelque chose comme

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

a et b doivent avoir des types connus. En revanche, tr1 / boost / phoenix / lambda bind vous permet de faire ceci:

 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" 

Notez que les types A et B ne sont pas fixes ici. Ce n'est que lorsque f est réellement utilisé que ces deux seront déduits.

La syntaxe C ++ 0x lamdba est plus lisible que la syntaxe bind. Une fois que vous obtenez plus de 2-3 niveaux de liaison, votre code devient pratiquement illisible et difficile à maintenir. Je préférerais la syntaxe lambda plus intuitive.

Un des avantages de lambdas est qu’ils sont bien plus utiles lorsque vous devez append un peu de logique à une fonction existante.

Avec bind, vous êtes obligé de créer une nouvelle fonction / méthode / foncteur même si la logique n’est nécessaire qu’à cet endroit. Vous devez trouver un nom approprié et rendre le code moins compréhensible, car cela peut potentiellement vous séparer de la logique associée.

Avec lambda, vous pouvez append la nouvelle logique à l’intérieur du lambda (mais vous n’êtes pas obligé de le faire s’il est logique de créer un nouvel appelable).

Je pense que c’est plus une question de goût. Les personnes qui comprennent rapidement les nouvelles technologies ou qui sont familiarisées avec la functional programming préféreront probablement la syntaxe lambda, tandis que les programmeurs plus conservateurs préféreront définitivement la liaison, car elle est plus conforme à la syntaxe C ++ traditionnelle.

Une telle décision devrait être prise en coordination avec les personnes qui travailleront avec le code, probablement par un vote majoritaire.

Ce qui ne change toutefois pas le fait que la syntaxe lambda est beaucoup plus puissante et propre.

C ++ 0x lambdas remplacent essentiellement la liaison. Il n’y a rien que vous puissiez lier pour que vous ne puissiez pas recréer un wrapper lambda sortingvial pour obtenir la même chose. std :: tr1 :: bind ira dans le sens de std :: bind1st, etc une fois que le support lambda sera largement répandu. Ce qui est bien, car pour une raison quelconque, la plupart des programmeurs ont de la difficulté à comprendre.