web-dev-qa-db-fra.com

Quand devrais-je utiliser std :: lié?

Chaque fois que je dois utiliser std::bind, Je finis par utiliser une Lambda à la place. Alors quand devrais-je utiliser std::bind? Je viens de finir de le supprimer d'une base de code et j'ai trouvé que les Lambdas étaient toujours plus simples et plus claires que std::bind. N'est pas std::bind complètement inutile? Ne devrait-il pas être obsolète à l'avenir? Quand devrais-je préférer std::bind aux fonctions de Lambda? (Il doit y avoir une raison pour laquelle il est entré dans la norme en même temps que Lambdas.)

J'ai également remarqué que de plus en plus de personnes connaissent que Lambdas (alors ils savent ce que les Lambdas font). Cependant, beaucoup moins de personnes sont familières avec std::bind et std::placeholders.

37
gnzlbg

Voici quelque chose que vous ne pouvez pas faire avec une Lambda:

std::unique_ptr<SomeType> ptr = ...;
return std::bind(&SomeType::Function, std::move(ptr), _1, _2);

Lambdas ne peut pas capturer des types de déplacement uniquement; Ils ne peuvent capturer que des valeurs par copie ou par référence de Lvalue. Bien que c'était certes une question temporaire qui soit activement résolue pour C++ 14;)

"Plus simple et plus claire" est une question d'opinion. Pour des cas de liaison simples, bind peut prendre beaucoup moins de dactylographie. bind est également ciblé uniquement sur la liaison de fonction, donc si vous voyez std::bind, vous savez ce que vous regardez. Alors que si vous utilisez une Lambda, vous devez examiner la mise en œuvre de la Lambda pour être certaine de ce qu'elle fait.

Enfin, C++ ne décompresse pas les choses simplement parce qu'une autre caractéristique peut faire ce qu'elle fait. auto_ptr a été obsolète parce que c'est intrinsèquement dangereux à utiliser et il y a une alternative non dangereuse.

30
Nicol Bolas

Vous pouvez créer des objets polymorphes avec std::bind que vous ne pouvez pas avec Lambdas, c'est-à-dire. L'enveloppe d'appel est retourné par std::bind peut être invoqué avec différents types d'arguments:

#include <functional>
#include <string>
#include <iostream>

struct Polly
{
  template<typename T, typename U>
    auto operator()(T t, U u) const -> decltype(t + u)
    { return t + u; }
};

int main()
{
  auto polly = std::bind(Polly(), std::placeholders::_1, "confusing");

  std::cout << polly(4) << polly(std::string(" this is ")) << std::endl;    
}

J'ai créé ceci comme un puzzle pas un exemple de bon code, mais il démontre des emballages d'appel polymorphes.

23
Jonathan Wakely