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

SL & STL C++ Discussion :

question sur la fonction bind


Sujet :

SL & STL C++

  1. #1
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut question sur la fonction bind
    Bonjour

    J'ai une question concernant l'utilisation de bind

    La fonction std::get<0> permet de récupérer le premier élément d'une paire
    et std::get<1> le deuxième.

    la fonction bind est définie ici:
    http://msdn.microsoft.com/en-us/library/bb982702.aspx

    Par exemple, quand on fait:

    Code :

    Ca renvoie cos(1.0).

    Maintenant, quand je fais ceci:

    Code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    pair<int, double> UnePaire0 =make_pair(20,3.2);
    bind(std::get<0,int,int>,UnePaire0);
    ou

    Code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    pair<int, double> UnePaire0 =make_pair(20,3.2);
    bind(std::get<0>,UnePaire0);
    ca me renvoie des erreurs, alors que

    Code :

    fonctionne très bien.

    Avez vous une idée?
    Merci

  2. #2
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Bonjour.

    Citation Envoyé par deubelte Voir le message
    ca me renvoie des erreurs
    Ce serait pas mal de dire lesquelles...

    Tu as essayé ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::pair<int, double> UnePaire0 = std::make_pair(20, 3.2);
    std::bind(std::get<0, int, double>, UnePaire0);
    En y réfléchissant, je ne suis pas sûr qu'on puisse passer une fonction template en paramètre d'une autre fonction template...
    Je ne suis pas assez calé pour ça.

    Sinon, les foncteurs select1st et select2nd peuvent être utiles.
    Par contre, ce sont des extensions GNU, alors ils ne sont pas forcément disponibles partout.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #include <ext/functional>
     
    std::pair<int, double> UnePaire0(20, 3.2);
    __gnu_cxx::select1st< std::pair<int, double> >()(UnePaire0) // std::get<0>(UnePaire0) => 20
    __gnu_cxx::select2nd< std::pair<int, double> >()(UnePaire0) // std::get<1>(UnePaire0) => 3.2
    Steph.

  3. #3
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    En fait, sur ma distribution, select1st et select2nd ne sont que des sous-classes vides de respectivement _Select1st et _Select2nd, définies dans un fichier appelé depuis l'en-tête <functional>, et appartenant à l'espace de nom std.

    Pour information, en voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    template<typename _Pair>
    struct _Select1st : public unary_function<_Pair,
                                              typename _Pair::first_type>
    {
        typename _Pair::first_type&
        operator()(_Pair& __x) const
        { return __x.first; }
     
        const typename _Pair::first_type&
        operator()(const _Pair& __x) const
        { return __x.first; }
    };
     
     
    template<typename _Pair>
    struct _Select2nd : public unary_function<_Pair,
                                              typename _Pair::second_type>
    {
        typename _Pair::second_type&
        operator()(_Pair& __x) const
        { return __x.second; }
     
        const typename _Pair::second_type&
        operator()(const _Pair& __x) const
        { return __x.second; }
     };

  4. #4
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Sinon, les foncteurs select1st et select2nd peuvent être utiles.
    Par contre, ce sont des extensions GNU, alors ils ne sont pas forcément disponibles partout.
    je suis sur VC2010.


    En y réfléchissant, je ne suis pas sûr qu'on puisse passer une fonction template en paramètre d'une autre fonction template...
    bind n'est pas template. Il n'y a qu'une fonction tempalte ici, c'est la fonctions std::get<>

  5. #5
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    template<class F, class... BoundArgs>
    unspecified bind(F&&, BoundArgs&&...);
    template<class R, class F, class... BoundArgs>
    unspecified bind(F&&, BoundArgs&&...);
    bind est bien template.

    Je crois que le problème vient du fait qu'il y a deux version de get qui ont des signature différentes et que donc bind n'arrive pas à déterminer tout seul ses paramètre template.

    Une solution est de passer par une fonction intermédiaire dont le compilateur pourrait déterminer la signature sans ambiguité.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    template<size_t I, class T1, class T2>
    T1 tmp(const std::pair<T1, T2>& p)
    { return std::get<I>(p); }
    Et l'utiliser dans bind à la place de get. (de la même manière)

  6. #6
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Sinon, les foncteurs select1st et select2nd peuvent être utiles.
    Par contre, ce sont des extensions GNU, alors ils ne sont pas forcément disponibles partout.
    je suis sur VC2010.
    Oui, je m'en doutais un peu.
    C'est pour cela que je t'ai mis le code des foncteurs.

    Du coup tu as le choix :
    • soit tu utilises l'astuce de Flob90 ;
    • soit tu réécris ces foncteurs.

  7. #7
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Je crois que le problème vient du fait qu'il y a deux version de get qui ont des signature différentes et que donc bind n'arrive pas à déterminer tout seul ses paramètre template.
    Oui c'est ça.
    Il y a un conflit entre les deux fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename IDX, typename T1, typename T2>
    type_retour& get(std::pair<T1, T2>& p);
     
    template<typename IDX, typename T1, typename T2>
    const type_retour& get(const std::pair<T1, T2>& p);
    Il faut lever l'ambiguité en précisant le type de retour souhaité à bind:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::pair<int, double> UnePaire0 = std::make_pair(20, 3.2);
    std::bind<int&>(std::get<0, int , double>, UnePaire0);

  8. #8
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Oui c'est ça.
    Il y a un conflit entre les deux fonctions :

    Ok, la seule différence entre les deux, c'est le fait que le type retourné pour l'un est constant, et non pour l'autre.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const type_retour& get(const std::pair<T1, T2>& p);
    Mais je ne vois pas en quoi le fait de spéficier

    std::bind<int&> permet de lever l'ambiguité sur la constante.

    De plus, dans ce cas, on appelle quelle version des deux fonctions?

    Merci

  9. #9
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Mais je ne vois pas en quoi le fait de spéficier

    std::bind<int&> permet de lever l'ambiguité sur la constante.
    Ben car pour sélectionner la version constante il faudrait écrire : std::bind<const int&> ...

  10. #10
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Ok, si je reprends la définition de bind, j'ai:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bind<typename _Ret,typename _Fty>(_Fty _Val)
    Pourquoi est il pas nécessaire de spécifier le deuxième argument template?
    je m'attendais à faire: bind<Type1, Type2>

  11. #11
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    D'une manière générale, il n'est pas nécessaire de préciser explicitement la valeur des variables template que le compilateur peut déterminer tout seul (autrement dit, sans qu'il y ait d'ambiguïté).
    C'est pour cette raison que l'on peut ne spécifier qu'un paramètre template à la fonction std::get, alors qu'elle en a trois : les deux autres sont déterminés automatiquement à partir du type de l'argument passé à la fonction.
    Mais ce n'est pas une erreur d'indiquer explicitement tous les paramètres template, à condition de rester cohérent.

    Pour le problème qui nous intéresse, comme il l'a été dit plus haut, le compilateur ne sait pas laquelle des deux fonctions std::get il doit utiliser.
    Normalement, cette ambiguïté est levée grâce à la signature de la fonction, sauf qu'ici elle est censée être trouvée toute seule.
    Les paramètres template pourraient différencier les fonctions, sauf qu'ils sont identiques dans les deux cas.

    Heureusement, le type de retour, qui est différent pour les deux fonctions, et requis pour la fonction std::bind.
    Une fois qu'il est défini, il n'y a plus qu'une seule fonction qui correspond, et l'ambiguïté est levée.

  12. #12
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    D'une manière générale, il n'est pas nécessaire de préciser explicitement la valeur des variables template que le compilateur peut déterminer tout seul (autrement dit, sans qu'il y ait d'ambiguïté).
    Je viens réellement d'apprendre qqch. Je pensais qu'on pouvait effectivement ne pas spécifier les tempalte quand on avait des paramètres template par défaut.
    Mais y a pas de paramètres par défaut dans cette fonction bind.

    Mais dans ma distribution, quand je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::bind<int&>(std::get<0>, UnePaire0);
    j'ai comme erreur:

    1>------ Build started: Project: Proj1, Configuration: Debug Win32 ------
    1> src1.cpp
    1>c:\users\visual studio 2010\projects\proj1\proj1\src1.cpp(77): error C2664: 'std::tr1::_Bind_fty<_Fty,_Ret,_BindN> std::tr1::bind<int&,std::pair<_Ty1,_Ty2>>(_Fty,_Arg0)' : cannot convert parameter 1 from 'overloaded-function' to 'int &'
    1> with
    1> [
    1> _Fty=int &,
    1> _Ret=std::tr1::_Notforced,
    1> _BindN=std::tr1::_Bind1<std::tr1::_Callable_obj<int &,false>,std::pair<int,double>>,
    1> _Ty1=int,
    1> _Ty2=double,
    1> _Arg0=std::pair<int,double>
    1> ]
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Discussions similaires

  1. [Dates] Question sur les fonctions Date
    Par cerede2000 dans le forum Langage
    Réponses: 2
    Dernier message: 28/10/2006, 17h26
  2. Question sur la fonction recv
    Par Mr_Chut dans le forum Réseau
    Réponses: 14
    Dernier message: 15/09/2006, 12h43
  3. Question sur les fonctions "send()" et "recv(
    Par damien99 dans le forum MFC
    Réponses: 6
    Dernier message: 10/02/2006, 20h47
  4. Réponses: 1
    Dernier message: 08/02/2006, 11h18
  5. Réponses: 2
    Dernier message: 21/12/2005, 09h39

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