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 :

Stockage foncteur (encapsulation de fonctions)


Sujet :

C++

  1. #1
    Membre à l'essai
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    Points : 20
    Points
    20
    Par défaut Stockage foncteur (encapsulation de fonctions)
    Bonjour à tous,

    J'ai créée un implémentation de foncteurs permettant de stocker des pointeurs de fonctions de tout type. Je vous en donne un extrait :
    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
    class NullType {};
    class Functor {};
     
    template <class R = void(), class C = NullType>
    struct Function;
     
    /* Fonctions libres sans paramètre */
    template<class R>
    class Function<R()> : public Functor
    {
    private:
    	typedef R (*F)();
     
    public:
    	Function(F f) : m_f(f) {}
    	R operator ()() { return m_f(); }
     
    private:
    	F m_f;
    };
     
    /* [...] */
     
    /* Fonctions membres const à un paramètre */
    template <class R, class T1, class C>
    struct Function<R(C::*)(T1) const, C> : public Functor
    {
    private:
    	typedef R (C::*F)(T1) const;
     
    public:
    	Function(F f, C c) : m_f(f), m_c(c) {}
    	R operator ()(T1 t1) { return (c.*m_f)(t1); }
     
    private:
    	F m_f;
    	C m_c;
    };
    Voila mon problème : j'aimerai pouvoir stocker ces foncteurs, par exemple dans une list de la stl. Cependant ce n'est pas possible puisque tous les foncteurs sont d'un type différent. Exemple d'utilisation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void f() {} // une fonction libre
     
    Function<void ()> F(&f); // le foncteur qui encapsule cette fonction
    F(); // et l'utilisation du foncteur qui va appeler f()
    Si tous les foncteurs à stocker sont de type Function<void()> pas de probleme, mais ce n'est pas le cas.

    J'ai donc pensé à faire hériter les classes Function d'une classe mère commune Functor. Dans ce cas on peux effectivement stocker n'importe quel type de foncteurs (en utilisant le polymorphisme) mais il faudra alors faire un reinterpret_cast pour l'utiliser; de plus on perd les paramètres template (d'où le reinterpret_cast) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    /* en reprennant le bout de code précédent : */
    Functor* Foncteur = &F;
     
    /* pour l'utiliser : */
    (reinterpret_cast<Function<void()>*>(Foncteur))()
    Voila, j'espère avoir été assez clair. Est-ce que vous auriez une solution pour stocker ces foncteurs ?

    Merci d'avance.

  2. #2
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    ne réinvente pas la roue !
    regarde du coté de boost::function ou de <tr1/functional>
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  3. #3
    Membre à l'essai
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    Points : 20
    Points
    20
    Par défaut
    Certes je réinvente un peu la roue

    J'ai déjà regardé du coté de boost; mais je n'ai pas trouvé comment réaliser ce que je souhaite faire. A ma connaissance, on utilise boost.function à peu près de la même manière que mes foncteurs, à savoir qu'on met la signature de la fonction en paramètre template. C'est juste ?

    Sinon <tr1/functional> je ne connais pas; comment l'utilise-t-on ?

  4. #4
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut
    Sans préjuger de l'existence d'une bonne solution j'ai personnellement l'impression que l'abstraction nécessaire au stockage ne fait pas bon ménage avec la spécialisation introduite par les templates. J'aurais tendance à dire qu'il faut abandonner un des deux. Par exemple si tu limite la capacité de spécialisation à un nombre limité de triplets <class R, class T1, class C> alors tu pourrais définir des fonctions virtuelles operator() correspondantes au niveau de ta classe mère et faire l'appel que tu souhaite...mais c'est vraiment pas très élégant.

  5. #5
    Membre à l'essai
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    Points : 20
    Points
    20
    Par défaut
    Je ne suis pas sur d'avoir compris. Peux-tu me donner un exemple ?

    En gros je devrais créer autant de fonctions virtuelles operator () dans la classe mère que de spécialisations ?

  6. #6
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par xwindoo Voir le message
    Je ne suis pas sur d'avoir compris. Peux-tu me donner un exemple ?

    En gros je devrais créer autant de fonctions virtuelles operator () dans la classe mère que de spécialisations ?
    Oui c'est ça...tu vas me dire que c'est pourri et tu auras raison...

  7. #7
    Membre à l'essai
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    Points : 20
    Points
    20
    Par défaut
    Non ce n'est pas pourri, j'y avais pensé d'ailleurs.
    Mais y'a un problème qui se pose :

    que met on en paramètre de retour ? Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class Functor
    {
        virtual ??? operator()();
    };
    pour que les fonctions virtuelles soient adaptées à tous les types de fonctions, il faudrait rajouter un paramètre template :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <class R>
    class Functor
    {
        virtual R operator ()();
    };
    Et dans ce cas on retombe à la case départ : on pourra pas stocker des foncteurs de types de retour différents. Et ce, pareil pour les paramètres.

    Merci quand même pour ta réponse

  8. #8
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Voici un code qui illustre mon propos:
    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
     
    #include <iostream>
    #include <vector>
    #include <boost/function.hpp>
    #include <boost/bind.hpp>
     
    struct Fct
    {
        Fct(int ii):m_i(ii){}
        int foo(int num){return m_i*num+5;}
    private:
        int m_i;
    };
     
    int affine(int num)
    {
        return (2*num+1);
    }
     
    int affine2(int num)
    {
        return (4*num-2);
    }
     
    int main(int argc, char const **argv)
    {
        Fct fct(10);
     
        std::vector< boost::function1<int, int> > vec;
     
        vec.push_back(affine);
        vec.push_back(affine2);
        vec.push_back( boost::bind(&Fct::foo,fct,_1) );
     
        const int k=vec.size();
        for(int i=0;i<k;i++)
    	std::cout<<vec[i](42)<<std::endl;
     
        return 0;
    }
    La seule limitation de ce code dans la signature de la fonction. Dans mon exemple, il faut que la fonction renvoit un int après en avoir prit un en paramètre.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  9. #9
    Membre à l'essai
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    Points : 20
    Points
    20
    Par défaut
    Merci pour cette précision.

    Cette seule limitation est justement celle qui me gène. Je voudrai stocker des foncteurs renvoyant des types différents avec des paramètres différents.

  10. #10
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Citation Envoyé par xwindoo Voir le message
    Merci pour cette précision.

    Cette seule limitation est justement celle qui me gène. Je voudrai stocker des foncteurs renvoyant des types différents avec des paramètres différents.
    Quel est l'intérêt ?
    Car pour moi, on stocke dans un même conteneur un ensemble cohérent de choses en vue de leur appliquer le même traitement.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  11. #11
    Membre à l'essai
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    Points : 20
    Points
    20
    Par défaut
    Oui je sais, je réinvente encore la roue... mais j'aime bien ça :
    ce que je voudrai faire c'est un système de message pour une GUI. En gros il ressemblera au système de Qt avec connect. On pourra alors associer à chaque message une (ou plusieurs) fonction qui le traiterons. Et donc suivant le message, la signature sera différente (suivant d'autres choses aussi). Je dois donc stocker dans une liste associative les messages avec leur foncteurs.

    Ce que je pourrais faire c'est établir une liste de prototype de fonction par rapport à chaque message et ensuite faire un reinterpret_cast, mais le problème se pose avec les fonctions membres d'une classe : je dois aussi connaitre le type de la classe (paramètre template C dans mon cas).

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Tu as regardé signal/slot de boost ?

    Pourquoi ne pas associer à chaque message une liste de fonction, liste dont le type dépend du message, plutôt que de tout mettre en vrac pour au final downcaster (tu en aurais besoin au moment d'appeler la fonction de toutes façons...) ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  13. #13
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Je plussoie Loic.
    D'ailleurs tu remarquera que Qt impose l'unicité des types des paramètres en signals et slots.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  14. #14
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Si tu cherches en regardant dans mon profil l'un des premiers sujets que j'avais créé dans le forum C++, j'avais posé la même question et il y avait eu pas mal de réponses intéressantes... Je te conseille très vivement d'y jeter un oeil

  15. #15
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    Citation Envoyé par xwindoo Voir le message
    Et dans ce cas on retombe à la case départ : on pourra pas stocker des foncteurs de types de retour différents. Et ce, pareil pour les paramètres.
    Pourquoi veux-tu mettre des pointeurs de fonctions dans une std::list ?
    Sais-tu ce que c'est qu'un pointeur ? Sous Windows par exemple c'est un DWORD de 4 octets ou adresse mémoire 32bits..
    En fonction de cela et par conséquent si tu as un pointeur sur une fonction à une adresse xxxxx, il se peut fortement que l'OS déplace l'exécutable ou le process en mémoire et ton adresse xxxx n'est plus du tout valide.
    Donc ta std::list ne sera plus valide et tu risques d'avoir des plantages...
    Quel est le but final du projet que veux-tu faire ?

  16. #16
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    Citation Envoyé par xwindoo Voir le message
    Oui je sais, je réinvente encore la roue... mais j'aime bien ça :
    ce que je voudrai faire c'est un système de message pour une GUI. En gros il ressemblera au système de Qt avec connect. On pourra alors associer à chaque message une (ou plusieurs) fonction qui le traiterons. Et donc suivant le message, la signature sera différente (suivant d'autres choses aussi). Je dois donc stocker dans une liste associative les messages avec leur foncteurs.
    .
    Pardon je n'avais pas vu les réponses.
    ( J'essaie veinement de rechercher dans la doc de MFC ) ; si tu prends MFC qui est similaire à Qt le problème est résolu avec des espèces de macros qui sont contenues dans une table ; Si tu veux par exemple intercepter le clic gauche de la souris il ya appel d'une macro sous MFC.
    Dans ton cas il vaut mieux s'inspirer des méchanismes de Qt

  17. #17
    Membre régulier
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par xwindoo Voir le message
    Oui je sais, je réinvente encore la roue... mais j'aime bien ça :
    ce que je voudrai faire c'est un système de message pour une GUI. En gros il ressemblera au système de Qt avec connect. On pourra alors associer à chaque message une (ou plusieurs) fonction qui le traiterons...
    Question un peu naïve peut-être. Quel est l'intérêt par rapport à un système classique d'abonnement ?

    De mémoire grosso modo :

    Message == un classe dérivée d'une classe mère "event"
    Une fonction qui doit traiter le message == une instance de classe possédant une méthode processEvent(const event&)
    Liste de foncteurs = un manager/dispatcher d'évènements auxquelles s'abonnent les différentes instances de classe pour être prévenues d'un message à traiter.

  18. #18
    Membre à l'essai
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    Points : 20
    Points
    20
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Pourquoi ne pas associer à chaque message une liste de fonction, liste dont le type dépend du message, plutôt que de tout mettre en vrac pour au final downcaster (tu en aurais besoin au moment d'appeler la fonction de toutes façons...) ?
    Citation Envoyé par Mat.M Voir le message
    ( J'essaie veinement de rechercher dans la doc de MFC ) ; si tu prends MFC qui est similaire à Qt le problème est résolu avec des espèces de macros qui sont contenues dans une table ; Si tu veux par exemple intercepter le clic gauche de la souris il ya appel d'une macro sous MFC.
    J'avais pensé à établir une liste de prototypes de fonctions, mais je n'ai pas trouvé le moyen; j'ai essayé avec des macros, des structures, des typedefs pour finalement avoir un truc bizarre sans queue ni tête.
    MFC utilise effectivement des espèces de macros qu'on peux trouver dans afxmsg_.h, leur syntaxe est un peu bizarre et si j'ai bien compris le fonctionnement général, je peux dire que ce n'est pas exactement ce qu'il me faut (pointeurs de fonctions prédéfini sans foncteur; d'ailleurs je ne sais pas comment ils sont stocker...).

    Citation Envoyé par JolyLoic Voir le message
    Tu as regardé signal/slot de boost ?
    Je en connais pas les signaux de boost et préfèrerai m'en passer. Mais je vais y regarder un coup.

    Si tu cherches en regardant dans mon profil l'un des premiers sujets que j'avais créé dans le forum C++, j'avais posé la même question et il y avait eu pas mal de réponses intéressantes... Je te conseille très vivement d'y jeter un oeil
    Je vais regarder ça en détail.

    Citation Envoyé par tnarol Voir le message
    Message == un classe dérivée d'une classe mère "event"
    Dans mon cas non, un message = instance d'un class 'Event'.

    Citation Envoyé par tnarol Voir le message
    Une fonction qui doit traiter le message == une instance de classe possédant une méthode processEvent(const event&)Liste de foncteurs = un manager/dispatcher d'évènements auxquelles s'abonnent les différentes instances de classe pour être prévenues d'un message à traiter.
    Oui, j'utilise pour cela le pattern observer (Listener).
    En fait, l'utilisateur pourra choisir entre la méthode du listener et les foncteurs pour associé une fonction à un control en particulier et un message en particulier.

    Merci pour toutes vos réponses

  19. #19
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    http://www.developpez.net/forums/sho...d.php?t=230448 > voilà le topic dont j'ai parlé.

  20. #20
    Membre à l'essai
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    Points : 20
    Points
    20
    Par défaut
    Alp> Apparemment l'implémentation que tu en a tiré ne permet pas l'encapsulation de fonctions membres puisqu'il faudrait spécifier la classe à laquelle la fonction est associée dans le dyamic_cast or on ne le connais pas et on ne peux pas le connaitre.
    Par contre c'est assez intéressant pour la liste des paramètres. je vais creuser.

    (http://www.developpez.net/forums/sho...=230448&page=2)

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Encapsuler des fonctions
    Par StryceK dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 23/02/2014, 15h15
  2. [XL-2007] Macro stockage de données en fonction de 3 critères
    Par Jacques33 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 12/03/2012, 11h12
  3. [SHELL] - Encapsuler les fonctions de copie
    Par Mika2008 dans le forum Linux
    Réponses: 11
    Dernier message: 26/09/2010, 10h36
  4. Encapsulation des fonctions en javascript
    Par nicko_73 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 28/10/2009, 09h29
  5. Réponses: 4
    Dernier message: 30/09/2008, 18h13

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