std::bind
est pour une application de fonction partielle .
Autrement dit, supposons que vous ayez un objet fonction f
qui prend 3 arguments:
f(a,b,c);
Vous voulez un nouvel objet fonction qui ne prend que deux arguments, définis comme:
g(a,b) := f(a, 4, b);
g
est une "application partielle" de la fonction f
: l'argument du milieu a déjà été spécifié, et il en reste deux.
Vous pouvez utiliser std::bind
pour obtenir g
:
auto g = bind(f, _1, 4, _2);
C'est plus concis que d'écrire une classe de foncteurs pour le faire.
Il existe d'autres exemples dans l'article auquel vous créez un lien. Vous l'utilisez généralement lorsque vous devez passer un foncteur à un algorithme. Vous avez une fonction ou un foncteur qui fait presque le travail que vous voulez, mais qui est plus configurable (c'est-à-dire a plus de paramètres) que l'algorithme n'en utilise. Donc, vous liez des arguments à certains des paramètres et laissez le reste pour l'algorithme à remplir:
// raise every value in vec to the power of 7
std::transform(vec.begin(), vec.end(), some_output, std::bind(std::pow, _1, 7));
Ici, pow
prend deux paramètres et peut s'élever à n'importe quelle puissance, mais tout ce qui nous importe est de monter à la puissance de 7.
En tant qu'utilisation occasionnelle qui n'est pas une application de fonction partielle, bind
peut également réorganiser les arguments d'une fonction:
auto memcpy_with_the_parameters_in_the_right_flipping_order = bind(memcpy, _2, _1, _3);
Je ne recommande pas de l'utiliser simplement parce que vous n'aimez pas l'API, mais elle a des utilisations pratiques potentielles, par exemple parce que:
not2(bind(less<T>, _2, _1));
est une fonction inférieure ou égale (en supposant un ordre total, bla bla). Cet exemple n'est normalement pas nécessaire car il existe déjà un std::less_equal
(il utilise l' <=
opérateur plutôt que <
, donc s'ils ne sont pas cohérents, vous pourriez en avoir besoin, et vous devrez peut-être également visiter l'auteur de la classe avec un clic). C'est le genre de transformation qui survient si vous utilisez un style de programmation fonctionnel.
myThread=boost::thread(boost::bind(&MyClass::threadMain, this))
std::function
?pow
exemple ne compile pas. Puisqu'ilpow
s'agit d'une fonction surchargée, vous devez spécifier manuellement quelle surcharge. La liaison ne peut pas laisser être déduite par l'appelant du foncteur résultant. Par exemplestd::transform(vec.begin(), vec.end(), out.begin(), std::bind((double (*)(double, int))std::pow, _1, 7));
std::bind
s'accompagne parfois de l'this
utilisation comme 2ème argument. Pouvez-vous s'il vous plaît élaborer ce cas d'utilisation?std::placeholders::_1
. Il m'a fallu un certain temps pour savoir pourquoi cela ne compilait pas.L'une des principales utilisations de std :: function et std :: bind est l'utilisation de pointeurs de fonctions plus généralisés. Vous pouvez l'utiliser pour implémenter un mécanisme de rappel. L'un des scénarios les plus courants est que vous avez une fonction qui prendra beaucoup de temps à s'exécuter mais que vous ne voulez pas attendre son retour, vous pouvez alors exécuter cette fonction sur un thread séparé et lui donner un pointeur de fonction indiquant qu'elle callback une fois terminé.
Voici un exemple de code pour savoir comment utiliser ceci:
la source
std :: bind a été voté dans la bibliothèque après la proposition d'inclure boost bind, principalement il s'agit d'une spécialisation partielle des fonctions dans laquelle vous pouvez corriger quelques paramètres et en changer d'autres à la volée. Maintenant, c'est une méthode de bibliothèque pour faire des lambdas en C ++. Réponse de Steve Jessop
Maintenant que C ++ 11 prend en charge les fonctions lambda, je ne ressens plus aucune tentation d'utiliser std :: bind. Je préférerais utiliser le curry (spécialisation partielle) avec la fonction de langue plutôt que la fonction de bibliothèque.
Les objets std :: function sont des fonctions polymorphes. L'idée de base est de pouvoir faire référence à tous les objets appelables de manière interchangeable.
Je vous indiquerai ces deux liens pour plus de détails:
Fonctions Lambda en C ++ 11: http://www.nullptr.me/2011/10/12/c11-lambda-having-fun-with-brackets/#.UJmXu8XA9Z8
Entité appelable en C ++: http://www.nullptr.me/2011/05/31/callable-entity/#.UJmXuMXA9Z8
la source
std::bind
n'a jamais existé sans lambdas - ces deux fonctionnalités ont été introduites dans C ++ 11. Nous avons eubind1st
etbind2nd
qui étaient des versions émaciées de C ++ 11 bind.Je l'ai utilisé il y a longtemps pour créer un pool de threads de plugins en C ++; Puisque la fonction prenait trois paramètres, vous pouvez écrire comme ceci
Supposons que votre méthode ait la signature:
Pour créer un objet fonction pour lier les trois paramètres, vous pouvez faire comme ceci
Maintenant, pour lier les paramètres, nous devons écrire une fonction de classeur. Alors, voilà:
Et, une fonction d'assistance pour utiliser la classe binder3 - bind3:
et ici nous comment l'appeler
Remarque: f3 (); appellera la méthode task1-> ThreeParameterTask (21,22,23);
Pour plus de détails sanglants -> http://www.codeproject.com/Articles/26078/AC-Plug-in-ThreadPool-Design
la source