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 de fonctions


Sujet :

C++

  1. #1
    Alp
    Alp est déconnecté
    Expert confirmé

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut Stockage de fonctions
    Salut à tous,

    Alors c'est dans le contexte d'un langage de script.

    Je souhaiterais pouvoir associer(surement dans une map) à chaque chaine la fonction qui lui correspond :
    "f(a,b)" => f(a,b)

    Seulement, en templatant etc, je me retrouve quand même face à un problème : comment pouvoir avec _un type_ pouvoir représenter toutes les fonctions ?
    Soit FuncType ce type, je ferais alors un :
    std::map < std::string , FuncType > ma_map;

    Ensuite je la remplirai ce n'est pas un problème. Mais comment designer le tout pour obtenir un FuncType ?

    Merci

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Il faut distinguer selon les paramètres de la fonction

  3. #3
    Alp
    Alp est déconnecté
    Expert confirmé

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Et pour le type de retour?

    En gros, tu concevrais ça comment?

    A la limite, faire une map pour les fonctions sans arguments, une pour celles à 1 argument, une pour celles à 2 arguments, etc, ça peut être faisable.

    Dans ce cas là tu ferais comment ?

  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    boost::function pour stocker les fonctions (function<void ()>, function<void (int)>, function<void (int, int)>, ... par exemple) avec boost::bind pour les créer comme il faut.

  5. #5
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Hmm en fait tu peux peut-être faire un wrapper universel...
    Un truc du style

    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
    struct ifunction_base
    {
        template<typename R> virtual operator()();
        template<typename R, typename V1> virtual operator()(const V1&);
        template<typename R, typename V1, typename V2> virtual operator()(const V1&, const V2&);
    };
     
    template<typename R> class ifunction : public ifunction_base
    {
        boost::function<R> f_;
     
    public:
        ifunction(const boost::function<R>& f) : f_(f)
        {
        }
     
        R operator()()
        {
             return f_();
        }
    };
     
    class Function
    {
       ifunction_base* f_;
     
    public:
       template<typename R> Function(const boost::function<R>& f) : f_(new ifunction<R>(f));
       {
       }
     
       template<typename R> R operator()()
       {
            return f_();
       }
     
       ~Function()
       {
            delete f_;
       }
    };

  6. #6
    Alp
    Alp est déconnecté
    Expert confirmé

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Hmm, j'y ai pensé.
    Mais ça marchera pas si je mets des boost::function0<...> boost::function1<...> etc ..., non ?
    Puisqu'il faudrait un seul type, pour définir ma map.

    EDIT : j'ai rien dit, j'avais oublié qu'en fait on a la possibilité d'utiliser les deux : boost::function< > et boost::functionN< > . Désolé.

  7. #7
    Alp
    Alp est déconnecté
    Expert confirmé

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Ah loufoque, en effet j'étais pas allé aussi loin dans mon raisonnement.
    Je pense que ça devrait faire l'affaire.
    Par contre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    template<typename R> R operator()()
    {
            return f_();
    }
    Ca marche ça? Il me semblait que non. Que le compilo ne déduisait pas R tout seul.

  8. #8
    Alp
    Alp est déconnecté
    Expert confirmé

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    En rajoutant les R juste après virtual dans ifunction_base que tu avais oublié, et en corrigeant quelques fautes de frappes, le code donne ç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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    struct ifunction_base
    {
        template<typename R> virtual R operator()() = 0;
        template<typename R, typename V1> virtual R operator()(const V1&) = 0;
        template<typename R, typename V1, typename V2> virtual R operator()(const V1&, const V2&) = 0;
    };
     
    template<typename R> class ifunction : public ifunction_base
    {
        boost::function<R> f_;
     
    public:
        ifunction(const boost::function<R>& f) : f_(f)
        {
        }
     
        R operator()()
        {
             return f_();
        }
    };
     
    class Function
    {
       ifunction_base* f_;
     
    public:
       template<typename R> Function(const boost::function<R>& f) : f_(new ifunction<R>(f))
       {
       }
     
       template<typename R> R operator()()
       {
            return (*f_)();
       }
     
       ~Function()
       {
            delete f_;
       }
    };
    Et j'ai ces erreurs :
    main.cpp:6: error: invalid use of `virtual' in template declaration of `virtual R ifunction_base::operator()()'
    main.cpp:7: error: invalid use of `virtual' in template declaration of `virtual R ifunction_base::operator()(const V1&)'
    main.cpp:8: error: invalid use of `virtual' in template declaration of `virtual R ifunction_base::operator()(const V1&, const V2&)'
    main.cpp: In member function `R Function::operator()()':
    main.cpp:37: error: no match for call to `(ifunction_base) ()'
    avec g++, 3.x

    et
    .\Source1.cpp(6) : error C2072: 'operator ()' : initialization of a function
    .\Source1.cpp(6) : error C2898: 'R operator ()(void)' : member function templates cannot be virtual
    .\Source1.cpp(7) : error C2072: 'operator ()' : initialization of a function
    .\Source1.cpp(7) : error C2898: 'R operator ()(const V1 &)' : member function templates cannot be virtual
    .\Source1.cpp(8) : error C2072: 'operator ()' : initialization of a function
    .\Source1.cpp(8) : error C2898: 'R operator ()(const V1 &,const V2 &)' : member function templates cannot be virtual
    avec VC2005

  9. #9
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Les membres templates ne peuvent pas être virtuels.

  10. #10
    Alp
    Alp est déconnecté
    Expert confirmé

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Même si il y a encore des fautes car il ne faut pas qu'elles soient virtuelles pures, je me suis trompé, j'aimerais savoir pourquoi une fonction membre template ne peut être virtuelle, et donc comment faire?

  11. #11
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Alp
    j'aimerais savoir pourquoi une fonction membre template ne peut être virtuelle
    Personne n'a proposé la chose au commité sous une forme qui a convaincu suffisemment de monde pour faire passer la proposition.

    Cette réponse n'aide vraissemblablement pas. Je crois que le fond est que les deux concepts se marient mal en C++. J'aurais du mal à proposer une sémantique évidente, surtout quand on considère les spécialisations explicites, sans commencer à parler de la manière d'implémenter cette sémantique dans le cadre des implémentations traditionnelles de la généricité (génération du code spécialisé lors de la compilation) et des fonctions virtuelles (utilisation d'une table de pointeurs vers fonction) en C++.

  12. #12
    Alp
    Alp est déconnecté
    Expert confirmé

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    C'est vrai que cela se marie mal.
    Mais j'ai trouvé surprenant au début qu'ils soient carrément incompatibles.
    Je pensais que cela serait autorisé quand même.

    Qu'en est-il pour mon problème alors? Vois tu une autre solution ?

  13. #13
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Alp
    comment faire?
    Ajouter un niveau d'indirection de plus. Une piste à complèter:
    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
    template <typename R> struct ifunction0;
    template <typename R, typename P1> struct ifunction1;
     
    struct ifunction_base
    {
      template<typename R> R operator()();
      template<typename R, typename P1> R operator()(P1 const&);
    };
     
    template <typename R>
    struct ifunction0: ifunction_base
    {
      typedef R (*fnType)();
      ifunction0(fnType ptr) : myPtr(ptr) {}  
      R operator()() { return myPtr(); }
    private:
      fnType myPtr;
    };
     
    template <typename R, typename P1>
    struct ifunction1: ifunction_base
    {
      typedef R (*fnType)(P1 const&);
      ifunction1(fnType ptr) : myPtr(ptr) {}
      R operator()(P1 const& p1) { return myPtr(p1); }
    private:
      fnType myPtr;
    };
     
    template <typename R> R operator()()
    {
      ifunction0<R>* self = dynamic_cast<ifunction<R>*>(this);
      assert(self != 0);
      return self->operator()();
    }
     
    template <typename R, typename P1> R operator()(V1 const& p1)
    {
      ifunction1<R, V1>* self = dynamic_cast<ifunction<R, P1>*>(this);
      assert(self != 0);
      return self->operator()(p1);
    }

  14. #14
    Alp
    Alp est déconnecté
    Expert confirmé

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    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
    50
    51
    52
    53
    54
    #include <iostream>
     
    template <typename R> struct ifunction0;
    template <typename R, typename P1> struct ifunction1;
     
    struct ifunction_base {
        template<typename R> R operator()();
        template<typename R, typename P1> R operator()(P1 const&);
    };
     
    template <typename R> struct ifunction0: ifunction_base {
        typedef R (*fnType)();
        ifunction0(fnType ptr) : myPtr(ptr) {}
     
        R operator()()
        {
            return myPtr();
        }
        private:
        fnType myPtr;
    };
     
    template <typename R, typename P1> struct ifunction1: ifunction_base
    {
        typedef R (*fnType)(P1 const&);
        ifunction1(fnType ptr) : myPtr(ptr) {}
        R operator()(P1 const& p1)
        {
            return myPtr(p1);
        }
        private:
        fnType myPtr;
    };
     
    template <typename R> R ifunction_base::operator()()
    {
        ifunction0<R>* self = dynamic_cast<ifunction0<R>*>(this);
        assert(self != 0); return self->operator()();
    }
     
    template <typename R, typename P1> R ifunction_base::operator()(P1 const& p1)
    {
        ifunction1<R, P1>* self = dynamic_cast<ifunction1<R, P1>*>(this);
        assert(self != 0); return self->operator()(p1);
    }
     
    int f() { return 42; }
     
    int main()
    {
        ifunction_base* pf = new ifunction0<int>(f);
        // comment appeler f ?
        return 0;
    }
    Voilà ou en est le code.

    Mais comment invoquer f maitenant ?

  15. #15
    Alp
    Alp est déconnecté
    Expert confirmé

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Je pensais que ça serait (*pf) ()
    mais j'ai
    main.cpp:54: error: no match for call to `(ifunction_base) ()'

  16. #16
    Alp
    Alp est déconnecté
    Expert confirmé

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    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
    50
    51
    52
    53
    54
    55
    56
    #include <iostream>
    #include <boost/function.hpp>
     
    template <typename R> struct ifunction0;
    template <typename R, typename P1> struct ifunction1;
     
    struct ifunction_base {
        template<typename R> R operator()();
        template<typename R, typename P1> R operator()(P1 const&);
        virtual ~ifunction_base() { }
    };
     
    template <typename R> struct ifunction0: ifunction_base {
        typedef R (*fnType)();
        ifunction0(fnType ptr) : myPtr(ptr) {}
     
        R operator()()
        {
            return myPtr();
        }
        private:
        fnType myPtr;
    };
     
    template <typename R, typename P1> struct ifunction1: ifunction_base
    {
        typedef R (*fnType)(P1 const&);
        ifunction1(fnType ptr) : myPtr(ptr) {}
        R operator()(P1 const& p1)
        {
            return myPtr(p1);
        }
        private:
        fnType myPtr;
    };
     
    template <typename R> R ifunction_base::operator()()
    {
        ifunction0<R>* self = dynamic_cast<ifunction0<R>*>(this);
        assert(self != 0); return self->operator()();
    }
     
    template <typename R, typename P1> R ifunction_base::operator()(P1 const& p1)
    {
        ifunction1<R, P1>* self = dynamic_cast<ifunction1<R, P1>*>(this);
        assert(self != 0); return self->operator()(p1);
    }
     
    int f() { return 42; }
     
    int main()
    {
        ifunction_base* pf = new ifunction0<int>(f);
        std::cout << pf->operator()<int>();
        return 0;
    }
    Voilà.
    Cependant je ne crois pas qu'il soit possible de s'abstraire à devoir connaitre le type de retour de la fonction ...

  17. #17
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Il n'y a rien qui permette de déduire le type du résultat. Donc tu dois le spécifier:Il n'y a guère d'intérêt à utiliser la syntaxe des opérateurs.

    Note que j'ai oublié qu'il faut absolument un membre virtuel dans ifunction_base pour que le dynamic_cast fonctionne. Par exemple le destructeur.

    Edit: j'avais pas vu qu'il y avait une deuxième page. Tu as tout trouvé tout seul.

  18. #18
    Alp
    Alp est déconnecté
    Expert confirmé

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Oui oui. En relisant le code je me suis aperçu qu'il manquait le destructeur virtuel.
    A la limite, si je me débrouille pour faire une map par type de retour, ça ira.
    Pour un langage de script très simple, je retournerai surement des int, des double peut être, et des strings.

    Merci en tout cas, bonne journée

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

Discussions similaires

  1. stockage des fonctions javascript
    Par dabac dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 30/03/2011, 17h38
  2. [Fonctions]Prix de stockage différents.
    Par UiYuki dans le forum Débuter
    Réponses: 8
    Dernier message: 20/10/2008, 09h49
  3. Réponses: 4
    Dernier message: 30/09/2008, 18h13
  4. Stockage foncteur (encapsulation de fonctions)
    Par xwindoo dans le forum C++
    Réponses: 25
    Dernier message: 11/07/2008, 16h21
  5. Réponses: 1
    Dernier message: 30/08/2006, 20h54

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