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 :

Foncteur et vecteur


Sujet :

C++

  1. #1
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut Foncteur et vecteur

    Depuis ce matin je n'arrive pas à mettre en oeuvre un vector de methode.

    J'ai un class A:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class A
    {
       void methode1();
       void methode2();
       void methode3();
       void methode4();
    /* et d'autre avec toujours le même prototype*/
    }
    Et j'aimerais pouvoir faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    std::vector<functor> vect_func;
    for_each(vect_func,print_name,execute);//syntaxe totalement fausse mais l'idée est là
    Il me faut donc aussi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class functor
    {
       string name;
       void print_name();
       void operator ();
    }
    Enfin je vous met tout ça pour avoir l'idée parce que là je suis un peu perdu dans mes foncteurs. Comme faire correspondre mes A::methodes avec un objet functor ?

    Pour résumé je souhaite juste faire un vecteur de pointeurs de fonctions (des méthodes d'une classe en faite) mais à la c++ (d'où les foncteurs)

    Dites moi si c'est possible déjà et après si vous pouvez m'aiguiller ça serait cool. Merci

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    L'idée est qu'il faut travailler avec... des pointeurs de fonctions (des "Callbacks" en somme )

    Tu devrais trouver, en effectuant une recherche sur le forum avec ce terme (callback), un tas de sujets qui devraient te permettre de t'en sortir
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Par défaut
    Tu peux regarder du côté de boost.function, c'est déjà tout prêt à l'emploi :p

  4. #4
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Ou chez Loki

  5. #5
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    Citation Envoyé par bolhrak Voir le message
    Tu peux regarder du côté de boost.function, c'est déjà tout prêt à l'emploi :p
    Pas possible d'utiliser Boost (c'est pas moi qui choisit les bilbio déjà je m'autorise la STL et y en a qui font une drole de tête )

    Les recherches sur le forum me renvoi souvent à des problèmes très spécifique (DLL, ...) ou alors justement résolu à l'aide de boot.function

    En épluchant forum et tuto j'en suis quand même arriver à ça :
    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
    
    typedef int (*PtrFonct)();
    
    struct functor
    {
      std::string m_name;
      PtrFonct m_pf;
      functor(const string &name, PtrFonct pf) : 
      m_name(name),m_pf(pf){};
    
      PtrFonct operator () ()
      {
        return (*m_pf)();
      }
    };
    /*...*/
      A a;
      functor f("methode1",&(PtrFonct)a.methode1);
      vector<functor> vect_f;
      vect_f.push_back(f);
      (*vect_f[0])();
    Mais j'ai cette erreur :
    error C2440: 'return' : cannot convert from 'int' to 'int (__cdecl *& )(void)

    Ce mixte C - C++ m'éffraye un peu
    Ou chez Loki
    connait pas

  6. #6
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    Ok.
    Erreur résolue avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        return &(PtrFonct)(*m_pf)();
    et maintenant ça compile (éxécution par encore testée).
    Me reste toujours le sentiment de mélanger pointeurs de fonction à la C et foncteur à la C++

  7. #7
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    Patatras Access Violation à l'éxécution
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
      A a;
      functor f("methode1",&(PtrFonct)a.methode1());
      vector<functor> vect_f;
      vect_f.push_back(f);
     
      /*...*/
     
      functor pf = vect_f[0];
      std::cout<<pf.m_name<<endl;
      pf();
    J'affiche bien "methode1" dans la console mais l'access violation est sur la ligne uivante lors de l'appel pf();

  8. #8
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    Après vérification je me dis que mon problème à l'éxécution vient peut être de ça :
    Pourquoi ne peut-on pas passer une fonction membre là où on attend un pointeur de fonction ?

    Si c'est le cas une des solutions proposées, et celle qui m'interresse, est d'utiliser le type DWORD (MaClasse::*)(void*)

    Seulement je n'arrive pas à l'appliquer à mon cas. Au niveau du typedef ?

  9. #9
    doccpu
    Invité(e)
    Par défaut
    T'a essayé ?
    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
     
    class functor
    {
       string mName;
       void (*mFunction)(/*params*/);
    public
       functor(string name, void (*Fonction)(/*params*/));
       {
            this->mName=name;
            this->mFunction = Fonction;
       }
       ~functor();
       void print_name()
       {
            cout << this->mName << endl; // ou autre chose
       }
       void execute(/*params*/);
       {
            this->mFunction(/*params*/);
       }
    }
     
    void fUneFonction(/*params*/)
    {
    /**/
    }
     
    void main (/*...*/)
    {
        functor f("fUneFonction",&fUneFonction);
        f.print_name;
        f.execute(/*params*/);
    }
    la syntaxe est surement a corriger(j'ai pas testé) mais l'idée y est !

  10. #10
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Par défaut
    Alors plusieurs choses : la syntaxe pour les pointeurs de fonction est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    class A {
     
    void methode();
    };
     
    typedef void (A::*PtrFun)();
    PtrFun fun = &A::PtrFun;
    Il est impossible de stocker les résultat d'une invocation pour l'utiliser plus tard (comme tu sembles vouloir le faire):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    A a;
    Type  invocation= a.methode //<= invalide, a.methode n'a pas de type en C++ standard
    Ensuite si tu peux utiliser la librairie standard, elle fournit des wrappers de fonction membre (les classes mem_fun), à condition que tes méthodes ne prennent pas plus d'un arguments.

    Donc ton functor se contentera de contenir quelques informations supplémentaires :

    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
     
    <template class R, class T>
    class Functor {
     
    public:
     
        Functor(R (T::*p)(), const std::string& n): ptrFun(p), name(n) {}
        R operator()(T* obj) {/*Eventuellement affichage du nom de la methode ici*/return ptrFun(obj);}
     
    private:
     
        mem_fun_t<R,T> ptrFun;
        std::string name;
     
    };
    Ensuite il suffit de définir un foncteur, une fonction, bref n'importe quoi qui appelle l'opérateur() de tes foncteurs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class executor {
     
    public:
     
        template<class R, class F>
            R operator()(F* f) { return f();}
    };
    Tu peux ensuite executer ta suite de foncteurs via algo de la bibliothèque standard:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Executor executor;
    for_each(list.begin(), list.end(), executor);

  11. #11
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Citation Envoyé par bolhrak Voir le message
    Ensuite si tu peux utiliser la librairie standard, elle fournit des wrappers de fonction membre (les classes mem_fun), à condition que tes méthodes ne prennent pas plus d'un arguments.
    L'écriture d'un mem_fun2_t pour avoir deux arguments est très facile etc...

  12. #12
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    Citation Envoyé par bolhrak Voir le message
    Ensuite si tu peux utiliser la librairie standard, elle fournit des wrappers de fonction membre (les classes mem_fun), à condition que tes méthodes ne prennent pas plus d'un arguments.
    Je ne connaissait pas. Merci
    Citation Envoyé par bolhrak Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Executor executor;
    for_each(list.begin(), list.end(), executor);
    Mon problème est de remplir cette liste avec methode1, methode2, ... Je ne parviens pas à trouver la syntaxe correcte.
    Sur certains post j'ai pu lire que cette méthode nécessitait des méthodes statiques ce qui n'est pas le cas des miennes. Des idées là dessus sachant que je ne peux modifier que très peu les méthodes de Class A ?

  13. #13
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    Citation Envoyé par doccpu Voir le message
    T'a essayé ?
    facile avec une fonction non membre

  14. #14
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Par défaut
    Citation Envoyé par befalimpertinent Voir le message
    Mon problème est de remplir cette liste avec methode1, methode2, ... Je ne parviens pas à trouver la syntaxe correcte.
    Sur certains post j'ai pu lire que cette méthode nécessitait des méthodes statiques ce qui n'est pas le cas des miennes. Des idées là dessus sachant que je ne peux modifier que très peu les méthodes de Class A ?
    Tu remplis ta liste avec les foncteurs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    typedef Functor<void, A> MyFunc;
     
    MyFunc a1(&A::methode1);
    MyFunc a2(&A::methode2);
    //... etc
    list.push_back(a1);
    list.push_back(a2);
    La définition précédente de la classe Executor n'est pas tout à fait correcte étant donné que tu as besoin d'une instance sur laquelle appeler les méthodes stockées dans les foncteurs. Il suffit de le modifier légèrement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template<class R, class T>
    class Executor {
     
    public:
     
            explicit Executor(T* obj): p_obj(obj) {}
            template<class Functor>
            R operator()(F* f) {return f(p_obj);}
    };
    Ensuite pour exécuter tes méthodes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    A* a = new A;
    Executor executor(a);
    for_each(list.begin(), list.end(), executor);
    Apres tu peux améliorer un peu le code en prenant en paramète template de executor le functor et en fournissant les types de retour et la classe depuis celui-ci, mais ça devient du détail

  15. #15
    doccpu
    Invité(e)
    Par défaut
    Citation Envoyé par befalimpertinent Voir le message
    facile avec une fonction non membre
    même avec fonctions membres le principe est le même tu fais un pointeur private a la classe sur la methode que tu veux warper et tu l'appelle dans la methode execute de la classe, que ce soit une methode membre d'une autre classe ou non.

  16. #16
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    juste par curiosité c'est dans quel contexte que tu peut pas utiliser la stl ?

  17. #17
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    La SL et la STL si. Et heureusement pour moi (je dois être le seul à l'utiliser d'ailleurs)
    Boost par contre pas possible. Je suppose qu'ils estiment (mes chefs de projets, les autres developpeurs) qu'il n'est pas assez "stable" au sens ou les versions ce succèdent (comme ce fut le cas à une époque pour la STL) Vivement que ça soit intégré dans la norme en tout cas.
    Et puis bon ils font certes du C++ à la C mais ils ont quand même beaucoup plus d'expérience que moi donc je me voit mal leur dire : "mé heu Boost is magic ! I want it"
    Et comme le projet repose sur une archi qui a déja quelques années on dispose des templates "équivalents" (Tableau<> vs vstd::vector<>), enfin le pensent-ils (car rien ne vaut la STL n'est ce pas )

    Quand je serai chef, moi aussi j'imposerai mes choix face aux glandus qui sorte de la fac comme moi
    Mais en attendant avec juste 1 an d'expérience... je vais pas tout réécrire

  18. #18
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par befalimpertinent Voir le message
    La SL et la STL si. Et heureusement pour moi (je dois être le seul à l'utiliser d'ailleurs)
    Boost par contre pas possible. Je suppose qu'ils estiment (mes chefs de projets, les autres developpeurs) qu'il n'est pas assez "stable" au sens ou les versions ce succèdent (comme ce fut le cas à une époque pour la STL) Vivement que ça soit intégré dans la norme en tout cas.
    Et puis bon ils font certes du C++ à la C mais ils ont quand même beaucoup plus d'expérience que moi donc je me voit mal leur dire : "mé heu Boost is magic ! I want it"
    Et comme le projet repose sur une archi qui a déja quelques années on dispose des templates "équivalents" (Tableau<> vs vstd::vector<>), enfin le pensent-ils (car rien ne vaut la STL n'est ce pas )

    Quand je serai chef, moi aussi j'imposerai mes choix face aux glandus qui sorte de la fac comme moi
    Mais en attendant avec juste 1 an d'expérience... je vais pas tout réécrire
    Mais tu pourrais pas juste prendre le header qui t'intéresse ? C'est juste du HPP à inclure, tout est template...

    Au pire, tu l'utilises, sans le dire à tes chefs, ils n'y verront que du feu. Tu rajoutes le header function.hpp avec ses quelques dépendances éventuelles (très peu), sans le mettre dans un répertoire "boost".

    Je ne crois pas que la licence de boost soit restrictive, elle est assez libre.

Discussions similaires

  1. Utilisation des vecteurs
    Par EmilieG dans le forum MFC
    Réponses: 12
    Dernier message: 19/03/2004, 16h28
  2. [math] somme de plusieurs vecteurs à 3 dimensions
    Par teska dans le forum Mathématiques
    Réponses: 5
    Dernier message: 04/06/2003, 21h40
  3. Récuperer les coordonnées d'un vecteur
    Par kerzut dans le forum OpenGL
    Réponses: 5
    Dernier message: 15/04/2003, 11h51
  4. Zoom sur des vecteurs ou lignes
    Par mat.M dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 25/11/2002, 10h40
  5. matrices * vecteur
    Par delire8 dans le forum Algorithmes et structures de données
    Réponses: 15
    Dernier message: 07/09/2002, 14h15

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