IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Boost C++ Discussion :

je ne comprends pas ce boost::bind


Sujet :

Boost C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Points : 13
    Points
    13
    Par défaut je ne comprends pas ce boost::bind
    je regarde l'exemple serveur fonctionnant avec boost::asio :
    http://www.boost.org/doc/libs/1_51_0...hat_server.cpp

    il y a une ligne qui me pose problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     acceptor_.async_accept(new_session->socket(),
            boost::bind(&chat_server::handle_accept, this, new_session,
              boost::asio::placeholders::error));
    la partie que je n'arrive pas à saisir est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::bind(&chat_server::handle_accept, this, new_session, boost::asio::placeholders::error)
    le premier argument &chat_server::handle_accept correspond à la fonction q'uon bind (dites moi si j'ai tort : mais il s'agit bien d'une référence ? donc il appelle la fonction non pas depuis un objet mais depuis la classe ?)

    cette fonction est défini comme tel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     void handle_accept(chat_session_ptr session,
          const boost::system::error_code& error)
      {
        if (!error)
        {
          session->start();
        }
     
        start_accept();
      }
    moi je ne vois que deux arguments, or dans le bind il y en a trois après &chat_server::handle_accept... pourriez vous m'expliquer ?

    de plus ne connaissant pas bind j'ai regardé cette page :
    http://www.boost.org/doc/libs/1_51_0...bind/bind.html

    prenons l'exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct F
    {
        int operator()(int a, int b) { return a - b; }
        bool operator()(long a, long b) { return a == b; }
    };
     
    F f;
     
    int x = 104;
     
    bind<int>(f, _1, _1)(x);
    je ne vois pas l'intérêt de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bind<int>(f, _1, _1)(x);
    au lie de
    pourriez-vous aussi m'expliquer ?

    de manière général je n'arrive pas à trouver d'exemple d'utilisation dans lequel je me dirais : « ha, ben là boost::bind va m'aider!! » auriez-vous en tête un exemple d'utilisation ?

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    • &chat_server::handle_accept correspond bien à la fonction membre de la classe chat_server que l'on veut "binder", mais c'est son adresse.
    • Nous avons ensuite new_session et boost::asio::placeholders::error qui correspondent bien aux arguments passés à la fonction.
    • Le deuxième argument this que tu vois est là car on a besoin d'une instance de la classe afin de pouvoir appeler la fonction.
      On aura en gros un appel
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      this->handle_accept(new_session, boost::asio::placeholders::error)
      Je te conseille de lire ce sujet de la FAQ C++.


    Pour ce qui est de l'exemple, il y a comme tu le présentes peu d'intérêt de choisir l'un plutôt que l'autre.
    Il peut y en avoir par contre lorsqu'il est combiné à boost::function. Ce message pourra t'éclairer.
    Une autre utilisation que l'on peut en faire concerne les algorithmes de la STL.
    Dernière modification par Invité ; 09/10/2012 à 03h51.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Points : 13
    Points
    13
    Par défaut
    merci pour tes explications, le message sur le forum de Laurent Gomila je l'avais lu, mais j'avoue ne pas le comprendre... la librairie BOOST c'est quelque chose que je découvre en ce moment.

    concernant la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::bind(&chat_server::handle_accept, this, new_session, boost::asio::placeholders::error)
    ton expliquation est parfaitment claire, mais d'où sais-tu qu'il fallait mettre this en deuxième position. Dans la documentation que j'ai lu sur le site de boost à aucun moment ça n'apparait (à moins que j'ai loupé le truc, comme c'est du ingliche...) après avoir lu ton message j'ai essayé de localisé l'API de boost sur le net, j'ai fait échec...

    mais j'ai quand même encore une question, est-ce que, le code suivant est correcte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::bind(this->chat_server::handle_accept, new_session, boost::asio::placeholders::error)
    P.S. : je n'ai pas mon pc avec le compilo en ce moment...

  4. #4
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    Bonjour begre1929 et bienvenue sur le forum C++

    Un point important, bind est maintenant inclut dans la nouvelle norme du C++11. Si tu utilises un compilateur récent, tu n'as pas besoin de boost

    Le principe de bind est en fait assez simple. Bind permet de créer un "fonction object", c'est à dire un objet qui encapsule l'appel d'une fonction.

    Bind peut appeler une fonction libre (ou membre static) directement ou appeler une fonction membre (et dans ce cas, le premier paramètre de bind est l'objet sur lequel doit être appelé la fonction membre)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    bind(f); // appel de f()
    binf(&A::f, a); // appel de a.f()
    La fonction est appelée en utilisant des variable "interne" à l'objet et/ou des paramètres qui sont passé à l'objet-fonction et qui transmis à la fonction (à l'aide des placeholder)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    bind(f, 1); // appel de f(1)
    bind(f, 1, 2); // appel de f(1, 2)
    Les placeholder peuvent être vu comme la création d'une nouvelle fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    bind(f, _1); // créé une fonction g qui prend 1 paramètre : g(x) = f(x)
    bind(f, _2, _1); // créé une fonction g qui prend 2 paramètre : g(x, y) = f(y, x)
    bind(f, 10, _1); // créé une fonction g qui prend 1 paramètre : g(x) = f(10, x)


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::bind(&chat_server::handle_accept, this, new_session,          boost::asio::placeholders::error)
    Cette ligne créé donc un objet-fonction qui appellera la fonction handle_accept de la classe chat_server sur l'objet this en lui passant les paramètres new_session et error

    mais d'où sais-tu qu'il fallait mettre this en deuxième position
    Il sait que c'est une fonction membre d'une classe et que donc le premier paramètre à passer ensuite est un objet correspondant à cette classe (this ici, mais ça peut être n'importe quel objet de type chat_server)

    mais j'ai quand même encore une question, est-ce que, le code suivant est correcte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::bind(this->chat_server::handle_accept, new_session, boost::asio::placeholders::error)
    Non, la syntaxe this->chat_server::handle_accept n'a pas de sens

    dites moi si j'ai tort : mais il s'agit bien d'une référence ?
    Non. Ne pas confondre une référence et l'opérateur "address_of". Là, &f n'est pas une référence, mais permet de créer un pointeur de fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    bind<int>(f, _1, _1)(x);
    bind<int>(f, x, x)();
    Alors, oui le résultat est le même. Par contre, c'est bien 2 choses différentes qui sont créés. Dans le premier cas, on créé un objet-fonction qui prend 1 paramètre. Puis cette objet-fonction est appelé avec le paramètre x :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    auto g = bind<int>(f, _1, _1); // créé la fonction g qui prend 1 paramètre
    g(x); // appel de g(x)
    Dans le second cas, on créé un objet-fonction qui ne prend aucun paramètre. Puis on appelle cet objet sans paramètre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    auto g = bind<int>(f, x, x); // créé la fonction g qui prend aucun paramètre
    g(); // appel de g()

    de manière général je n'arrive pas à trouver d'exemple d'utilisation dans lequel je me dirais : « ha, ben là boost::bind va m'aider!! » auriez-vous en tête un exemple d'utilisation ?
    donc il appelle la fonction non pas depuis un objet mais depuis la classe ?
    Tu ne vois pas les cas d'utilisation parce que tu te trompes sur ce que fait bind. Bind n'appelle pas une fonction, il créé un objet permettant d'appeler une fonction. Il est alors possible de passer cette fonction comme paramètre d'une autre fonction
    Dans le premier exemple avec async_accept, le but n'est pas d'appeler chat_server::handle_accept tout de suite, mais de dire "async_accept devra appeler chat_server::handle_accept lors qu'elle est déclenché"

    Plus généralement, bind pourra être utilisé lorsque l'on souhaite pouvoir modifier un comportement dynamiquement

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Points : 13
    Points
    13
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    Bonjour begre1929 et bienvenue sur le forum C++
    merci!
    Citation Envoyé par gbdivers Voir le message
    Un point important, bind est maintenant inclut dans la nouvelle norme du C++11. Si tu utilises un compilateur récent, tu n'as pas besoin de boost
    j'avais effectivement vu des exemples qui utilisent std au lieu de boost. J'en ferai de même dans mes utilisations.
    Citation Envoyé par gbdivers Voir le message
    Le principe de bind est en fait assez simple. Bind permet de créer un "fonction object", c'est à dire un objet qui encapsule l'appel d'une fonction.
    Citation Envoyé par gbdivers Voir le message
    Tu ne vois pas les cas d'utilisation parce que tu te trompes sur ce que fait bind. Bind n'appelle pas une fonction, il créé un objet permettant d'appeler une fonction. Il est alors possible de passer cette fonction comme paramètre d'une autre fonction
    Dans le premier exemple avec async_accept, le but n'est pas d'appeler chat_server::handle_accept tout de suite, mais de dire "async_accept devra appeler chat_server::handle_accept lors qu'elle est déclenché"
    avec ta réponse et celle de Winjerome (concernant la FAQ), je vois maintenant bind comme un moyen de recréer une fonction membre en fonction libre, avec éventuellement un remaniement sur ses paramètres par utilisation des placeholders.

    je ne voulais pas écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::bind(this->chat_server::handle_accept, new_session, boost::asio::placeholders::error)
    mais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::bind(this->handle_accept, new_session, boost::asio::placeholders::error)
    copié+collé... même si là je devrais plutôt dire sélectionné+clique bouton milieu, mais c'est plus long à écrire...

    Citation Envoyé par gbdivers Voir le message
    Plus généralement, bind pourra être utilisé lorsque l'on souhaite pouvoir modifier un comportement dynamiquement
    je t'avouerai que bind ça me semble être plus une amélioration de la présentation du code, que d'un outil qui s'ajoute pouvant m'aider à résoudre des problèmes si c'est moi qui écris le code. Quoique avec bind je me demande si le function object n'est pas mieux géré au niveau de la mémoire, puisque créé et détruit que localement, est-ce ça ton propos sur la dynamique ?

    ne maitrisant pas tout les outils que j'ai à ma disposition, si j'avais dû utiliser une fonction membre je l'aurais recopié dans un header que j'aurais inclue pour en faire une fonction libre (aux erreurs de copiés+collés près).

    Par contre si je lisais du code à autrui, là bind, à prime abord, devrait m'aider à identifier un groupe de fonctions créées depuis une fonction membre (maintenant que bind et moi ne sommes plus des inconnus)

    bon l'exemple,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::bind(&chat_server::handle_accept, this, new_session, boost::asio::placeholders::error)
    montre quand même un intérêt lorsque la function est membre d'une classe écrite par un tiers. Ça j'avoue que c'est un avantage.

    Si éventuellement je dis quelques chose qui n'a pas de sens me le dire... parce qu'il m'arrive d'hésiter, voir de renoncer, d'utiliser des termes propres à la programmation de peur de dire des bêtises...

  6. #6
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    Alors, c'est pas faux que bind permet d'utiliser une fonction membre comme une fonction libre (c'est pas la seule méthode). Par contre, c'est un peu réducteur.

    Plus généralement, bind pourra être utilisé lorsque l'on souhaite pouvoir modifier un comportement dynamiquement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // une fonction permettant de rechercher un élément dans une liste
    int MaFonctionDeRecheche(vector<int> const& v, std::function<bool(int, int)>);
     
    bool PlusPetitQue(int x, int y); // teste si x < y
    bool PlusGrandQue(int x, int y); // teste si x > y
     
    int main() {
         vector<int> v = { 1, 2, 3, 4, 5, 6 };
         cout << MaFonctionDeRecheche(v, PlusPetitQue) << endl; // affiche le plus petit élément
         cout << MaFonctionDeRecheche(v, PlusGrandQue) << endl; // affiche le plus grand élément
    }
    C'est ce que l'on fait pas exemple avec les algo de la STL.


    Pour être plus généraliste, si tu as une fonction qui demander de lui passer une fonction ayant une signature spécifique, bind permet de prendre n'importe quelle fonction et de l'adapter pour qu'elle puisse être utilisé dans la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    f(function<void(int)>); // prend une fonction qui possède 1 argument de type int
    void g(string, int); // fonction qui prend 2 arguments de type string et int
     
    f(g); // erreur, g n'a pas la bonne définition
    auto g2 = bind(g, "toto", _1); // créé une fonction g2 qui prend 1 argument de type int et qui appel g avec "toto" et l'argument passé à g2
    f(g2); // ok, g2 à la bonne définition

  7. #7
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 196
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 196
    Points : 17 165
    Points
    17 165
    Par défaut
    Je profite que le sujet soit encore vivant... quelqu'un peut-il m'expliquer le mécanisme interne des placeholders (les _1, _2 et autres…).

    Peut-on les reproduire ou relèvent-ils de l'intelligence des compilateurs?

  8. #8
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    Réponse simple (ou presque...) : puisque boost les implémentente bien avant la norme C++11, c'est indépendant du compilateur et on peut les reproduire. Comment ? En lisant le code source de boost

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Points : 13
    Points
    13
    Par défaut
    en lisant ton code :
    Citation Envoyé par gbdivers Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    f(function<void(int)>); // prend une fonction qui possède 1 argument de type int
    void g(string, int); // fonction qui prend 2 arguments de type string et int
     
    f(g); // erreur, g n'a pas la bonne définition
    auto g2 = bind(g, "toto", _1); // créé une fonction g2 qui prend 1 argument de type int et qui appel g avec "toto" et l'argument passé à g2
    f(g2); // ok, g2 à la bonne définition
    j'ai découvert :
    std::function http://en.cppreference.com/w/cpp/uti...ional/function
    auto : http://candrews.net/blog/2011/07/und...-auto-keyword/

    ton exemple emploie bind, auto et function là où pour arriver à un résultat similaire j'aurai copié+modifié la fonction...

    j'ai pas d'autre question concernant bind. Ne sachant pas si en mettant résolu vous pouvez encore discuter, je laisse le message ouvert pendant 48h, après quoi je le mettrai en résolu... sauf si éventuellement j'ai une question qui m'interroge, où si je vois que vous discutez.

    en tout cas grand merci pour ces réponses très détaillées, j'aurais un prof à coté de moi il ferait pas mieux.

  10. #10
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 196
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 196
    Points : 17 165
    Points
    17 165
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    Réponse simple (ou presque...) : puisque boost les implémentente bien avant la norme C++11, c'est indépendant du compilateur et on peut les reproduire. Comment ? En lisant le code source de boost
    Bonne réponse! Merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 31/08/2007, 21h05
  2. [thread][methodologie]Quelque chose que je ne comprends pas!
    Par norkius dans le forum Général Java
    Réponses: 5
    Dernier message: 16/03/2005, 14h01
  3. sql ne comprend pas mon where!et me demande des parametres
    Par marie10 dans le forum Langage SQL
    Réponses: 10
    Dernier message: 20/04/2004, 11h08
  4. [Rave] un message que je ne comprends pas
    Par Clotilde dans le forum Rave
    Réponses: 2
    Dernier message: 30/09/2003, 21h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo