web-dev-qa-db-fra.com

Différence entre C ++ 11 std :: bind et boost :: bind

Y a-t-il une différence entre les deux? Ou suis-je sûr de remplacer chaque occurrence de boost::bind par std::bind dans mon code et ainsi supprimer la dépendance à Boost?

66
Haatschii
  • boost::binda surchargé les opérateurs relationnels , std::bind ne fait pas.

  • boost::bindprend en charge les conventions d'appel non par défaut , std::bind n'est pas garanti (les implémentations de bibliothèque standard peuvent offrir cela comme une extension).

  • boost::bind fournit un mécanisme direct pour permettre à d'empêcher une évaluation impatiente des expressions de liaison imbriquées ( boost::protect ), std::bind ne fait pas. (Cela dit, on peut utiliser boost::protect avec std::bind s'ils le souhaitent, ou réimplémentez-le trivialement par eux-mêmes.)

  • std::bind fournit un mécanisme direct pour permettre de traiter tout foncteur défini par l'utilisateur comme une expression de liaison imbriquée afin de forcer une évaluation désirée ( std::is_bind_expression : [func.bind.isbind]/1, [func.bind.bind]/10), boost::bind ne fait pas.

86
ildjarn

Outre les différentes différences citées dans les autres réponses, voici deux autres différences:

  • boost::bind semble gérer les noms de fonctions surchargés dans certaines situations, tandis que std::bind ne les traite pas de la même manière. Voir faq c ++ 11

(en utilisant gcc 4.7.2, boost lib version 1_54)

void foo(){}
void foo(int i){}

auto badstd1 = std::bind(foo);  
//compile error: no matching function for call to bind(<unresolved overloaded function type>)
auto badstd2 = std::bind(foo, 1); 
//compile error: no matching function for call to bind(<unresolved overloaded function type>)
auto std1 = std::bind(static_cast<void(*)()>(foo)); //compiles ok
auto std2 = std::bind(static_cast<void(*)(int)>(foo), 1); //compiles ok
auto boost1 = boost::bind(foo, 1); //compiles ok
auto boost2 = boost::bind(foo); //compiles ok

Donc, si vous avez simplement remplacé tous les boost::bind avec std::bind, votre build pourrait se casser.

  • std::bind peut facilement se lier aux types lambda c ++ 11, tandis que boost::bind à partir du boost 1.54 semble nécessiter une entrée de l'utilisateur (sauf si return_type est défini). Voir boost doc

(en utilisant gcc 4.7.2, boost lib version 1_54)

auto fun = [](int i) { return i;};
auto stdbound = std::bind(fun, std::placeholders::_1);
stdbound(1);

auto boostboundNaive = boost::bind(fun, _1);  //compile error.
// error: no type named ‘result_type’ ...
auto boostbound1 = boost::bind<int>(fun, _1); //ok
boostbound1(1);
auto boostbound2 = boost::bind(boost::type<int>(), fun, _1); //ok
boostbound2(1);

Donc, si vous avez simplement remplacé tous les std::bind avec boost::bind, votre build pourrait également se casser.

23
orm

Outre la liste ci-dessus, boost :: bind a un point d'extension important: la fonction get_pointer () qui permet d'intégrer boost :: bind avec n'importe quel pointeur intelligent, par exemple. ATL :: CComPtr etc. http://www.boost.org/doc/libs/1_49_0/libs/bind/mem_fn.html#get_pointer

Par conséquent, avec boost :: bind, vous pouvez également lier un faiblesse_ptr: http://lists.boost.org/Archives/boost/2012/01/189529.php

16
Igor R.

Je n'ai pas la réponse complète mais std::bind utilisera des modèles variadiques plutôt que des listes de paramètres.

Les espaces réservés sont dans std::placeholders un péché std::placeholders::_1 plutôt que l'espace de noms global.

Je alias l'espace de noms avec lequel

namespace stdph=std::placeholders;

En dehors de cela, je n'ai eu aucun problème de mise à jour vers C++ 11

8
111111