182 votes

std :: function et std :: bind: que sont-ils et quand doivent-ils être utilisés?

Je sais ce que sont les foncteurs et quand les utiliser avec stl algos. mais n'a pas compris ce qu'il voulait dire dans ce sujet:

C ++ 11FAQ

Quelqu'un peut-il expliquer ce que std::bind et std::function sont, quand il faut utiliser, quelques exemples pour les débutants?

270voto

Steve Jessop Points 166970

std::bind est pour la fonction partielle de l'application.

Admettons que vous avez une fonction d'objet f qui prend 3 arguments:

f(a,b,c);

Vous voulez un nouvel objet de fonction qui prend deux arguments, définie comme suit:

g(a,b) := f(a, 4, b);

g est une "application partielle" de la fonction f: le moyen argument a déjà été spécifié, et il y a deux à gauche pour aller.

Vous pouvez utiliser std::bind pour obtenir de l' g:

auto g = bind(f, _1, 4, _2);

C'est plus concis qu'à écrire un foncteur de la classe de le faire.

Il existe d'autres exemples dans l'article que vous liez. En général, vous utilisez lorsque vous en avez besoin pour passer un foncteur d'un algorithme. Vous disposez d'une fonction ou d'un foncteur qui presque fait le travail que vous voulez, mais il est plus configurable (c'est à dire avoir plus de paramètres) que l'algorithme utilise. Si vous liez les arguments de certains paramètres, et de laisser le reste de 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 augmenter à tout pouvoir, mais tous nous élever à la puissance de 7.

Comme un usage occasionnel qui n'est pas partielle de la fonction de demande, bind pouvez également revoir l'ordre des arguments de la 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 il a le potentiel d'usages pratiques, parce que par exemple:

not2(bind(less<T>, _2, _1));

est un moins-que-ou-égal fonction (en supposant un total de la commande, bla bla). Cet exemple n'est normalement pas nécessaire puisque il y a déjà une std::less_equal (il utilise l' <= opérateur plutôt qu'en <, donc si ils ne sont pas compatibles, alors vous pourriez avoir besoin de cela, et vous pourriez aussi avoir besoin de visite de l'auteur de la classe avec un cluestick). C'est le genre de transformation qui arrive si vous utilisez un style fonctionnel de la programmation, bien que.

15voto

Sarang Points 811

std::bind a été voté dans la bibliothèque après la proposition visant à inclure boost lier, surtout, il est partielle de spécialisation de fonction où vous pouvez fixer quelques paramètres et de modifier les autres à la volée. Maintenant, c'est la bibliothèque de la façon de faire les lambdas en C++. Comme répondu par Steve Jessop

Maintenant que C++11 prend en charge les lambda fonctions, je ne me sens pas à la tentation d'utiliser std::bind plus. Je préfère utiliser nourrissage (partielle de spécialisation) avec fonctionnalité du langage que de la fonction de bibliothèque.

std::function objets sont des fonctions polymorphes. L'idée de base est de pouvoir se référer à toutes les appelable objets de façon interchangeable.

Je voudrais vous à ces deux liens pour plus de détails:

Lambda fonctions en C++11: http://www.nullptr.me/2011/10/12/c11-lambda-having-fun-with-brackets/#.UJmXu8XA9Z8

Callable entité en C++: http://www.nullptr.me/2011/05/31/callable-entity/#.UJmXuMXA9Z8

6voto

Alex Punnen Points 336

Je l'ai utilisé depuis longtemps pour créer un plugin de pool de threads en C++, Puisque la fonction était de prendre les trois paramètres que l'on peut écrire comme ceci

Supposons que votre méthode a pour signature:

int CTask::ThreeParameterTask(int par1, int par2, int par3)

Pour créer un objet de fonction de lier les trois paramètres que vous pouvez faire comme ceci

// a template class for converting a member function of the type int function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
public:
    explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
        :m_Ptr(_Pm) //okay here we store the member function pointer for later use
    {}

    //this operator call comes from the bind method
    _Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
    {
        return ((_P->*m_Ptr)(arg1,arg2,arg3));
    }
private:
    _Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};

Maintenant, afin de lier les paramètres, nous avons à écrire un classeur fonction. Donc, ici, il va:

template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
    //This is the constructor that does the binding part
    binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
        :m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}


        //and this is the function object 
        void operator()() const
        {
            m_fn(m_ptr,m1,m2,m3);//that calls the operator
        }
private:
    _Ptr m_ptr;
    _Func m_fn;
    _arg1 m1; _arg2 m2; _arg3 m3;
};

Et, une fonction d'aide pour l'utilisation de la binder3 classe - bind3:

//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
    return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}

et voici comment l'appeler

F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3( 
          &CTask::ThreeParameterTask), task1,2122,23 );

Remarque: f3(); va appeler la méthode task1->ThreeParameterTask(21,22,23);

Pour plus de détails sanglants --> http://www.codeproject.com/Articles/26078/A-C-Plug-in-ThreadPool-Design

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