64 votes

Lier Vs Lambda?

J'ai une question sur quel style est 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é qui se recoupe.

Utilisation de lambda :

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

Utilisation de 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 cité. C'est-à-dire quels sont les avantages / inconvénients de l'un par rapport à l'autre?

47voto

dv_ Points 462

Les lambdas C ++ 0x sont monomorphes, alors que bind peut être polymorphe. 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. D'autre part, 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 fixés ici. Ce n'est que lorsque f est réellement utilisé que ces deux éléments seront déduits.

28voto

Thomas Petit Points 4100

Comme vous l'avez dit, la reliure et les lambdas ne sont pas tout à fait exactement visent le même objectif.

Par exemple, pour l'aide et de la composition des algorithmes de la STL, les lambdas sont les grands vainqueurs, à mon humble avis.

Pour illustrer, je me souviens vraiment une drôle de réponse, ici, sur un débordement de pile, où quelqu'un a demandé des idées pour de hex numéros de magie, (comme OxDEADBEEF, OxCAFEBABE, OxDEADDEAD etc.) et on m'a dit que si il a été un vrai programmeur C++ il aurait tout simplement de téléchargement d'une liste de mots anglais et de l'utilisation d'un simple one-liner de C++ :)

#include <iterator>
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

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

Cet extrait de code, dans le plus pur C++98, ouvrez les mots anglais fichier, l'analyse de chaque mot et de l'impression que ceux qui de longueur 8 avec 'a', 'b', 'c', 'd', 'e' ou 'f' lettres.

Maintenant, tournez sur C++0X et lambda :

#include <iterator>
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>

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

C'est encore un peu lourd à lire (principalement en raison de la istream_iterator d'affaires), mais beaucoup plus simple que le bind version :)

18voto

posharma Points 440

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

8voto

R Samuel Klatchko Points 44549

L'un des avantages de lambdas, c'est qu'ils sont plus utiles lorsque vous avez besoin d'ajouter un peu de gros de la logique sur le haut d'une fonction existante.

Avec bind, vous êtes obligé de créer une nouvelle fonction/méthode/foncteur même si la logique n'est jamais nécessaire, dans ce seul endroit. Vous devez venir avec un nom approprié, et il peut rendre le code moins compréhensible dans la mesure où il rend potentiellement diviser la logique.

Avec lambda, vous pouvez ajouter une nouvelle logique à l'intérieur de la lambda (mais ne sont pas obligés de s'il est judicieux de créer un nouveau callable).

3voto

Kornel Kisielewicz Points 26556

Je pense que c'est plus une question de goût. Les gens que de saisir rapidement de nouvelles technologies, ou sont familiers avec la programmation fonctionnelle préféreront probablement lambda de la syntaxe, tandis que les plus conservatrices, les programmeurs vont définitivement préfèrent lier, car il est plus à la hauteur avec la traditionnelle syntaxe C++.

Une telle décision doit être faite en collaboration avec les personnes qui vont travailler avec le code, probablement par le biais d'un vote à la majorité.

Ce qui ne change pas le fait, cependant, que la lambda syntaxe est beaucoup plus puissant et plus propre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X