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

Langage C++ Discussion :

transformer foncteur en pointeur de fonction ?


Sujet :

Langage C++

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 6
    Points : 5
    Points
    5
    Par défaut transformer foncteur en pointeur de fonction ?
    Bonjour,

    Je débute avec les foncteurs et j'aimerais un coup de main pour le problème suivant :

    Une classe que j'utilise (moveset) attend des pointeurs de fonctions en argument du constructeur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    moveset(particle (*pfInit)(rng*),
    	      void (*pfNewMoves)(long, particle &, rng*),
    	      int (*pfNewMCMC)(long, particle &, rng*));
    J'aimerais lui passer des foncteurs que j'ai créé, avec l'opérateur () ayant les même paramètres et sorties que les pointeurs de fonctions attendus.

    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
    class FuncInitialize
        {
        public:
          particle operator () (rng *pRng);
        };
     
    class FuncMove
        {
        public:
          void operator () (long lTime, particle & lastParticle, rng *pRng);
        };
     
    FuncInitialize fInitialize;
    FuncMove fMove;
     
    moveset my_move_set(&fInitialize, &fMove, NULL);
    Le compilateur refuse car le foncteur n'est pas reconnu comme pointeur de fonction.

    Merci de votre aide

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    J'ai bien peur qu'il n'y ait rien d'universel, car les foncteurs contiennent plus d'infos que les pointeurs de fonction.

    Mais ici, tu devrais pouvoir utiliser des pointeurs de fonction directement.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    Merci pour la réponse.
    En fait, j'ai pensé aux foncteurs parce que mes fonctions fIntitialize et fMove, utilisent des variables contextuelles que moveset ne peut pas connaitre.
    Je ne peux pas les passer en paramètres parce que ça modifierait la signature, donc j'ai pensé les mettre en attribut des foncteurs.

    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
    class FuncInitialize
        {
        protected:
          Node * _pNode;
        public:
          particle operator () (rng *pRng) { /* code faisant appel à _pNode */ };
          FuncInitialize(Node * pNode) : _pNode(pNode) {};
        };
     
    class FuncMove
        {
        protected:
          vector<Node>::iterator _iterNode;
        public:
          void operator () (long lTime, particle & lastParticle, rng *pRng) 
          { 
             /* code faisant appel à _iterNode */
             _iterNode++;
          };
          FuncMove(vector<Node>::iterator iterNode;) : _iterNode(iterNode) {};
        };
     
    vector<Node> nodeSequence;
    FuncInitialize fInitialize(nodeSequence.begin());
    FuncMove fMove(nodeSequence.begin());
    moveset my_move_set(&fInitialize, &fMove, NULL);

  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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Ton problème ici ce n'est pas ce que tu passes, mais ce que tu reçois. La classe moveset est trop peu flexible, avec une telle signature tu es obligé de passer des pointeurs vers fonctions libres ayant exactement ce prototype. Ni plus ni moins.

    Utilise plutôt une abstraction plus puissante du genre boost.function, ou, si ça te fait peur, développe cette abstraction toi-même. Ca ne sera pas aussi flexible mais si tu restreint le nombre de trucs différents que tu veux gérer, c'est faisable rapidement.

    Autre solution : si ça colle avec ton design, fais de ta classe moveset un template (genre moveset<TypeFunc1, TypeFunc2>). Là tu pourras passer n'importe quoi qui soit "appelable". Par contre ça te fait N classes moveset au lieu d'une seule, ce qui peut être très chiant. Ceci-dit on peut améliorer ça avec du type erasure.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    J'ai essayé boost::function de cette façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    vector<Node> nodes(10);
    boost::function<particle (rng *)> fInitialize = FuncInitialize(nodes[0]);
    boost::function<void (long , particle & , rng *)> fMove = FuncMove(nodes.begin());
    smc::moveset my_move_set(&fInitialize, &fMove, NULL);
    Le compliateur refuse :
    error: no matching function for call to ‘moveset::moveset(boost::function<particle(smc::rng*)>*, boost::function<void(long int, particle&, rng*)>*, NULL)’
    note: candidates are: moveset::moveset(particle (*)(rng*), void (*)(long int, particle&, rng*), int (*)(long int, particle&, rng*))
    Faut-il passer l'objet boost::function ou son adresse, pour qu'il soit converti ?

    Aucun des deux ne compile, alors est-ce que j'ai mal compris ?
    Extrait de la doc de Boost.Function :
    Generally, any place in which a function pointer would be used to defer a call or make a callback, Boost.Function can be used instead to allow the user greater flexibility in the implementation of the target. Targets can be any 'compatible' function object (or function pointer), meaning that the arguments to the interface designated by Boost.Function can be converted to the arguments of the target function object.
    PS: je ne peux pas modifier la classe moveset

  6. #6
    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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    PS: je ne peux pas modifier la classe moveset
    Dans ce cas ça ne sert pas à grand chose, le but était de modifier le type de paramètre reçu par la classe, pas celui que tu lui passes. Un boost::function ne sera pas plus compatible avec un pointeur sur fonction qu'un foncteur ou autre chose.

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

Discussions similaires

  1. [C++] Pointeur sur fonction ou foncteur ?
    Par Kaluza dans le forum Langage
    Réponses: 12
    Dernier message: 23/03/2010, 01h52
  2. Declaration de fonction retournant un pointeur sur fonction
    Par pseudokifaitladifférence dans le forum C
    Réponses: 5
    Dernier message: 11/08/2003, 19h37
  3. Matrice de pointeurs de fonctions
    Par sebduth dans le forum C
    Réponses: 15
    Dernier message: 18/07/2003, 14h03
  4. [Kylix] Pointeur de fonctions
    Par _dack_ dans le forum EDI
    Réponses: 1
    Dernier message: 03/07/2003, 10h17
  5. pointeur de fonction
    Par kardath dans le forum C
    Réponses: 4
    Dernier message: 28/12/2002, 14h39

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