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

C++ Discussion :

type de retour de std::bind


Sujet :

C++

  1. #21
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Y a t-il un moyen de faire ceci sans passer par decltype ?
    Est-ce que le type du foncteur renvoyé par std::bind est définit dans la norme ?
    Si oui, j'ai juste à regarder à quoi ces typedefs correspondent et essayer de passer outre.

  2. #22
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Bon, j'ai tenter de ruser mais sans grand succès. Après avoir lu plus précisément le header functional, je me suis rendu compte que les 2 premiers typedefs ne servaient à rien dans mon cas.
    Donc pour simplifier, j'ai ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef std::_Bind<Fc(Args...)> ResultFunctorType;
    j'ai malheureusement toujours un _ , j'ai donc voulus utiliser std::result_of.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef typename std::result_of<(decltype(std::bind<Fc,Args...>))(Fc, Args...)>::type R;
    Malheureusement, j'obtiens l'erreur suivante :

    error: a comma operator cannot appear in a constant-expression|

    Est-ce un bug ou est-ce normal ?
    Quelqu'un a une idée ?

  3. #23
    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
    Le type de retour de bind n'est pas définie.

    @Joe Dralliam: Je crois que le bind du dernier draft n'est pas le même que celui de boost, et ce 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
     
    #include<cstdlib>
    #include<cstddef>
     
    #include<functional>
    #include<tuple>
    #include<iostream>
     
    template<class Fc, class ...Arg>
    auto bind_tuple_first(Fc f, const std::tuple<Arg...>& t)
      -> decltype(std::bind(f, std::get<0>(t) ))
    { return std::bind(f, std::get<0>(t) ); }
     
    void foo(int,int){std::cout << 0;}
     
    int main ()
    {
      std::function<void (int,int)> f(foo);
      std::tuple<int> t(0);
      auto f2 = bind_tuple_first(f,t);
      f2(0);
      system("PAUSE"); 
      return EXIT_SUCCESS;
    }
    Ne compile pas, mais compile si tu ne mets q'un seul argument à foo, compile avec bind1st et l'erreur est la même que le code que j'ai mis plus haut qui n'utilise pas de decltype et autre (un auto mais on peut l'écrire sans).

    Et il me semble bien que si la fonction prend deux arguments, qu'on fait un bind(f,0), alors le retour est un wrapper sur quelque chose qu'on peut utiliser comme ca f2(0), et qui doit appeller f(0,0).

  4. #24
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Le type de retour de bind n'est pas définie.
    Comment est-ce possible ? De plus, mon typedef ResultFonctorType est bel et bien le type de retour de std::bind.

  5. #25
    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
    Bha, c'est possible car c'est écrit dans le draft :
    template<class F, class... BoundArgs>
    unspecified bind(F&& f, BoundArgs&&... bound_args);
    C'est donc à celui qui code la STL de faire comme il veut, dans ton cas ils ont appelé le type qui représente le wrapper _Bind<Fc(Arg...)>.

    Sans en être certain, je dirais que ce genre de chose va de pair avec l'introduction de auto decltype et des lambda qui permettent de moins s'attacher au type et plus aux opérations effectué.

  6. #26
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    C'est donc à celui qui code la STL de faire comme il veut, dans ton cas ils ont appelé le type qui représente le wrapper _Bind<Fc(Arg...)>.
    Ok merci de cette réponse. Je croyais que tu voulais dire que bind n'avais pas de type réel. En fait tu veux dire qu'il dépend de l'implémentation. Cependant, cela n'explique pas pourquoi std::result_of ne marche pas.

    Sans en être certain, je dirais que ce genre de chose va de pair avec l'introduction de auto decltype et des lambda qui permettent de moins s'attacher au type et plus aux opérations effectué.
    En effet.

  7. #27
    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
    decltype ne passe pas sur bind<>, car il n'arrive pas à déterminer le type de la fonction car il existe plusieurs versions.

    Mais si à la place d'utiliser result_of tu passes directement par decltype sur un appel à bind ca marche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef decltype(std::bind(F(),Arg()...)) R;
    Mais ca revient en gros à utiliser auto et -> decltype, comme on l'a fait au début du thread, c'est juste plus verbeux (et je suis presque certain que le code ne marchera pas mieux ...)

  8. #28
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Oui, mais la chose du début ne compile pas avec gcc4.5, je vais voir si celle la compile.

  9. #29
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef decltype(std::bind(Fc(),Args()...)) R;
    ne marche pas : le compilateur me dit qu'il ne peut appelé Fc sans paramètres.
    J'ai tout de même une question, à quoi servent les parenthèses après Args ?
    Pourquoi le compilateur n'accepte-il pas quand je met Fc sans les parenthèses ?
    (error=function returning a function).

  10. #30
    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
    6
     
    template<class Fc, class ...Arg>
    struct bind_trait
    {
      typedef decltype(std::bind(Fc(),Arg()...)) Type;
    };
    Compile sans problème chez moi.

    Si je me trompe pas Arg()... c'est comme Fc() (une instanciation), mais pour une liste d'argument, donc avec int,int, ca va faire 0,0 (si il y a zero-initialisation, chose dont je ne suis pas certain).

  11. #31
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Il faut donc un constructeur par défaut ? Ou je n'ai rien compris...

  12. #32
    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
    Avec cette technique oui, mais je crois que pour un premier jet tu peus te restreindre à des chose DefaultConstrcutible, tu verras après pour adapter.

    Je serrais partie sur un truc comme ca :
    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
     
    template<size_t N>
    struct Help
    {
      template<class F, class ...Arg>
      auto Do(F&& f, const std::tuple<Arg...>& t)
        -> decltype(Help<N-1>::Do(std::bind(f, std::get<(sizeof...(Arg))-N>(t)),t))
      { return Help<N-1>::Do(std::bind(f, std::get<(sizeof...(Arg))-N>(t)),t); }
    };
     
    template<>
    struct Help<0>
    {
      template<class F, class ...Arg>
      auto Do(F&& f, const std::tuple<Arg...>&)
        -> decltype(std::bind(f))
      { return std::bind(f); }
    };
     
    template<class F, class ...Arg>
    auto make(F&& f, const std::tuple<Arg...>& t)
      -> decltype(Help<sizeof...(Arg)>::Do(f, t))
    { return Help<sizeof...(Arg)>::Do(f, t); }
    Ca compile, mais ca ne marche pas lors de l'utilisation, je dois oublier un détail sur les templates qui fait que ca marche pas. (et de toute manière ca ne marchera pas dans toute les situations à cause de bind AMHA)

  13. #33
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Mes objets ne sont pas default constructible, et j'ai déjà une méthode qui marche (ce qui me permet d'avancer tout de même). J'attendrais donc une version de gcc ou decltype et auto marcheront biens ou bien que quelqu'un trouve une autre solution...

  14. #34
    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
    Citation Envoyé par NoIdea Voir le message
    Mes objets ne sont pas default constructible, et j'ai déjà une méthode qui marche (ce qui me permet d'avancer tout de même). J'attendrais donc une version de gcc ou decltype et auto marcheront biens ou bien que quelqu'un trouve une autre solution...
    Tu pourrais poster ta solution stp ? J'aimerais tester

  15. #35
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef std::_Bind<Fc(Args...)> ResultFunctorType;
    Avec gcc4.5, sa marche parfaitement. Mais j'utilise toujours quelque chose de réserver à l'implémentation.

  16. #36
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Puisqu'on est sur la fonction bind, je voudrais savoir ce que renvoie la ligne de code:

    j'arrive pas à trouver.

    Merci

  17. #37
    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
    On l'a écrit plus haut : le type de retour de bind n'est pas spécifie, donc il faut utiliser auto. (où alors un typedef définit par ton compilateur qui représente le type de retour comme le fait NoIdea, mais ce 'nest pas portable).

    NB: Et les codes que j'ai posté avant (les premiers), ne compilait pas car j'avais oublié d'utiliser les placeholders, avec eux ca compile (je croyais qu'ils n'était pas obligatoire mais apparament si).

  18. #38
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Je suis d'accord avec l'utilisation d'auto, c'est ce que j'ai fait.

    Disons que je n'arrive pas à comprendre pourquoi cela compile:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    transform(V1.begin(),V1.end(),V1.begin(),bind(plus<int>(),3,(bind(less<int>(),5),_1)));
    Comme on le voit, on utilise bind avec plus<int>(), 3 ce qui est normal, mais aussia avec (bind(less<int>(),5),_1). Je m'étonne que cela compile car bind(less<int>(),5) ne signifie rien.

  19. #39
    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
    Ca applique l'algo transform à ta séquence avec le "functeur" (ca à un autre nom dans la norme, mais je trouve celui très clair), qui s'applique sur un paramètre n et qui retourne 3 + n.

    Il y a utilisation de l'opérateur , (qui permet d'appeller l'expression à gauxche avant celle de droite puis de retourner celle de droite). Mais ici j'ai l'impression qu'il ne sert à rien, c'est équivalent à :
    transform(V1.begin(),V1.end(),V1.begin(),bind(plus<int>(),3,_1));

  20. #40
    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
    J'ai une idée pour ton problème.

    Comme l'a dit Joe Dralliam, le problème vient de l'utilisation de decltype avec les template variadique.

    Mais ceci :
    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
     
    template<size_t N>
    struct Make
    {
      template<class F, class ...Arg, class ...Extracted>
      static auto Do(F f, const std::tuple<Arg...>& t, Extracted... arg)
        -> decltype(std::bind(f,Arg()...))
      { return Make<N-1>::Do(f, t, std::get<N-1>(t), arg...); }
    };
     
    template<>
    struct Make<0>
    {
      template<class F, class ...Arg, class ...Extracted>
      static auto Do(F f,const std::tuple<Arg...>& , Extracted... arg)
        -> decltype(std::bind(f,Arg()...))
      { return std::bind(f,arg...); }
    };
    Fonctionne bien pour les type DefaultConstructible (si on met ce qu'il y a après le retourne après le decltype ca ne marche plus, il ne supporte pas quelque chose à propos des variadics).

    Et si tu veus utiliser un fonction qui prend en paramètre des chose non constructible, en créant un nouveau foncteur à partir du premier qui transforme les paramètre non constructible en pointeur, ca devrait marcher :
    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
     
    template<class ...Arg>
    struct New
    {
      template<class F>
      struct Functor
      {
        F f;
        Functor(F p) : f(p) {}
        void operator()(Arg* ...arg)
        { f(*arg...); }
      };
     
      template<class F>
      static Functor<F> Do(F f)
      { return Functor<F>(f); }
    };
    Quelque chose comme ca (à améliorer et à vérifier si ca n'existe pas déja).

    Et ensuite il faut tranformer le tuples de la même manière : faire un tuple d'addresse sur les objet du premier tuple.

    Et je n'ai pas essayer, mais on peut surment faire bien mieux en ne tranformant que ceux qui ne sont pas constructible et en remplacant les non-constructible par des default constructible qui peuvent aussi être construit à partir des premiers. Je pense que ca permettrait d'utiliser directement le tuple.

    Un exemple "complet" (fait à la va-vite, fuite mémoire)
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     
    struct A { A(int){} };
     
    void foo(A,int,int){ std::cout << 0; }
     
    template<size_t N>
    struct Make
    {
      template<class F, class ...Arg, class ...Extracted>
      static auto Do(F f, const std::tuple<Arg...>& t, Extracted... arg)
        -> decltype(std::bind(f,Arg()...))
      { return Make<N-1>::Do(f, t, std::get<N-1>(t), arg...); }
    };
     
    template<>
    struct Make<0>
    {
      template<class F, class ...Arg, class ...Extracted>
      static auto Do(F f,const std::tuple<Arg...>& , Extracted... arg)
        -> decltype(std::bind(f,Arg()...))
      { return std::bind(f,arg...); }
    };
     
    template<class ...Arg>
    struct New
    {
      template<class F>
      struct Functor
      {
        F f;
        Functor(F p) : f(p) {}
        void operator()(Arg* ...arg)
        { f(*arg...); }
      };
     
      template<class F>
      static Functor<F> Do(F f)
      { return Functor<F>(f); }
    };
     
    int main ()
    {
      std::tuple<A*,int*,decltype(std::placeholders::_1)> t(new A(0),new int(),std::placeholders::_1);
      auto f1 = New<A,int,int>::Do(foo);
      auto f2 = Make<3>::Do(f1, t);
      f2(new int());
      system("PAUSE");
      return EXIT_SUCCESS;
    }

Discussions similaires

  1. Perte de type en retour de fonction
    Par Bebel dans le forum Langage
    Réponses: 8
    Dernier message: 22/12/2005, 13h54
  2. Type de retour de la valeur d'une msgbox
    Par Aurèl90 dans le forum Access
    Réponses: 10
    Dernier message: 02/12/2005, 17h45
  3. [Oracle 9.1] Types de retour d'une fonction PL/SQL
    Par ftrifiro dans le forum PL/SQL
    Réponses: 8
    Dernier message: 12/10/2005, 17h54
  4. [type de retour pour un update]
    Par viny dans le forum PostgreSQL
    Réponses: 7
    Dernier message: 21/03/2005, 22h08
  5. [type de retour dans une proc]
    Par viny dans le forum PostgreSQL
    Réponses: 5
    Dernier message: 19/03/2005, 15h35

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