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++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    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 : 33
    Localisation : Suisse

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

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    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 averti
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    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 éclairé
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    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 averti
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    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 éclairé
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    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 averti
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    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
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 527
    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 527
    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 ?

  9. #9
    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 : 33
    Localisation : Suisse

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

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    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)

  10. #10
    Membre averti
    Inscrit en
    Août 2006
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 62
    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.

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

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