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 :

Prototype de fonction difficile à comprendre


Sujet :

C++

  1. #1
    Membre éclairé Avatar de Nono Sto
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    350
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 350
    Par défaut Prototype de fonction difficile à comprendre
    Chères amies, chers amis du forum

    voici un prototype de fonction que je ne comprend pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void prog_dyn ( t_noeud * const arbre , double (* phi ) ( double ) , double p ) ;
    Mon problème c'est l'instruction suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double (* phi ) ( double )
    ,
    avec phi une fonction de type phi(x)=(x-100). je ne comprend pas comment implémenter une telle fonction, de plus je souhaite remplacer 100 par une variable K.

    Merci pour votre aide

  2. #2
    Membre expérimenté
    Avatar de Chatanga
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 211
    Par défaut
    Tu sembles pourtant bien avoir compris qu'il s'agit d'un pointeur sur fonction dont tu peux fournir une valeur à prog_dyn de la manière suivante.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    double phiPhi(double x)
    {
        return x - 100;
    }
     
    int main(int, char **)
    {
        prog_dyn(0, phiPhi, 250);
        return 0;
    }
    Pour remplacer 100 par K, c'est plus difficile. Je te propose ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template< int K >
    static double louLou(double x)
    {
        return x - K;
    }
     
    int main(int, char **)
    {
        prog_dyn(0, louLou<40>, 250);
    }
    La curryfication a toutefois ses limites en C++...

  3. #3
    Membre éclairé Avatar de Nono Sto
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    350
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 350
    Par défaut
    Merci

  4. #4
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Citation Envoyé par Chatanga Voir le message
    La curryfication a toutefois ses limites en C++...
    T'as aussi le droit de faire un bind.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    double f(double x, double factor)
    {
        return x - factor;
    }
     
    prog_dyn(0, boost::bind(f, _1, 40), 250);

  5. #5
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 058
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 058
    Billets dans le blog
    142
    Par défaut
    Bonjour,

    J'étais en train de faire le deuxième exemple de Chatanga (juste pour entrainement) et je ne vois pas du tout pourquoi on voudrais faire en utilisant le template, à la place d'utiliser simplement un argument de plus à la fonction (plus proche du dernier exemple avec le bind (et là, je me dis ... le bind me semble totalement inutile )).

    Pouvez vous m'expliquer un peu plus en détails s'il vous plait, pourquoi chercherai t'on à passer par un template, à la place d'ajouter un argument en plus.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  6. #6
    Membre expérimenté
    Avatar de Chatanga
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 211
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Pouvez vous m'expliquer un peu plus en détails s'il vous plait, pourquoi chercherai t'on à passer par un template, à la place d'ajouter un argument en plus.
    Parce que prog_dyn a simplement besoin d'une fonction phi:a->b et n'a pas à gérer des passages de paramètres supplémentaires qui n'ont aucun sens pour elle. Imaginons une implémentation de phi qui irait récupérer sa valeur de retour dans un fichier quelconque ; prog_dyn devrait-elle accepter un nouvel argument filename uniquement pour ça ?

    Sinon, utiliser boost::bind est assurément plus puissant que ma solution, d'autant que les paramètres autres que des entiers pourront être utilisés (dans mon exemple, K ne peut même pas être un double).

  7. #7
    Membre éclairé Avatar de Nono Sto
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    350
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 350
    Par défaut
    Cheres amies, chers amis du forum

    J'ai toujours un peu de mal dans l'utilisation de cette fonction, je l'ai modifié un peu:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    void noeud::pricing (noeud *const arbre ,void (*phi)(noeud,double), double p,double r );
    avec phi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    void noeud::phi (noeud *const arbre,double K);
    et dans le main lorsque j'appelle cette fonction dans le main j'ai une erreur qui s'affiche:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    node->pricing(node,(node,875),0.75,0.8);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    error C2664: 'noeud::pricing' : impossible de convertir le paramètre 2 de 'int' en 'void (__cdecl *)(noeud,double)
    Merci

  8. #8
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 032
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 032
    Billets dans le blog
    12
    Par défaut
    Je ne sais pas trop ce que tu cherches à faire, là.
    Ta fonction 'pricing' demande un pointeur de fonction, et apparemment tu essaies de lui passer des paramètres que tu aimerais mettre à ta fonction 'phi'. Le compilateur ne s'en sort pas, et moi non plus, d'ailleurs.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  9. #9
    Membre éclairé Avatar de Nono Sto
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    350
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 350
    Par défaut
    Merci

    je vais réfléchir à une autre solution, celle là me parait trop difficile.

  10. #10
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 058
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 058
    Billets dans le blog
    142
    Par défaut
    Citation Envoyé par Nono Sto Voir le message
    Merci

    je vais réfléchir à une autre solution, celle là me parait trop difficile.
    Pour ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    node->pricing(node,(node,875),0.75,0.8);
    J'aurais mis:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    node->pricing(node,node::phi(node,875),0.75,0.8);
    Ou alors (dependant de ce que dit le compilateur)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    node->pricing(node,&node::phi(node,875),0.75,0.8);
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  11. #11
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Pour ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    node->pricing(node,(node,875),0.75,0.8);
    J'aurais mis:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    node->pricing(node,node::phi(node,875),0.75,0.8);
    Ca, ça évalue la fonction node::phi avec les paramètres donnés, et ça passe en paramètre à pricing le résultat de cette évaluation.
    Citation Envoyé par LittleWhite Voir le message
    Ou alors (dependant de ce que dit le compilateur)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    node->pricing(node,&node::phi(node,875),0.75,0.8);
    Idem, sauf que tu envoie l'adresse à pricing().

    Avec le prototype
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void noeud::pricing (noeud *const arbre ,void (*phi)(noeud,double), double p,double r );
    Il faut que le prototype de phi soit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // dans une classe : 
    class X
    {
       static void phi(noeud* arbre, double valeur);
    };
    // en dehors d'une classe
    void phi(noeud* arbre, double valeur);
    Il est toutefois possible de faire les choses un peu différemment, en passant par les templates.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class noeud
    {
    public:
       template <class Functor>
       void pricing(noeud *const arbre , Functor phi, double p,double r)
       {
          // le code de procing doit être dans le fichier .h, parce que c'est une
          // fonction template
          ...
          phi(n, valeur);
          ...
       }
    };
    Le code suivant est alors valide :

    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
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    // cas phi1 : foncteur classique
    struct phi1
    {
      void operator()(noeud *const arbre, double v)
      { ... }
    };
    
    // cas phi2 : pointeur sur fonction
    void phi2(noeud *const arbre, double v);
    
    // cas phi3 et phi4 : fonctions membres d'une classe
    class X
    {
    public:
      static void phi3(noeud *const arbre, double v);
      void phi4(noeud *const arbre, double v);
    };
    
    // cas phi5: fonction phi membre de la classe noeud
    // requiert l'inclusion du header standard <functional>
    class noeud
    {
    public:
      // prototype court, car le premier paramètre est en fait l'instance de
      // noeud qui sera utilisée pour this. 
      void phi5(double v);
    };
    
    // ATTENTION - ATTENTION - ATTENTION - ATTENTION - ATTENTION
    // Le code ci-dessous est un peu compliqué pour un débutant. Il est
    // utile dans le cas où l'on veut passer en paramètre à pricing() une
    // fonction membre non statique d'une classe quelconque (le cas phi4).  
    // J'en dit plus un peu plus bas sur ce sujet très particulier. 
    // ATTENTION - ATTENTION - ATTENTION - ATTENTION - ATTENTION
    template <class C>
    struct phi_helper
    {
    private:
      C* m_instance;
      void (C::*m_membre)(noeud *const, double);
    
    public:
      phi_helper(C* c, void (C::*m)(noeud *const, double))
      : m_instance(c)
      , m_member(m)
      { }
      void operator()(noeud *const arbre, double v)
      {
        (m_instance->*m_membre)(arbre, v);
      }
    };
    
    template <class C>
    phi_helper<C> make_phi_helper(C* c, void (C::*m)(noeud *const, double))
    {
      return phi_helper<C>(c, m);
    }
    // ATTENTION - ATTENTION - ATTENTION - ATTENTION - ATTENTION
    // Fin du code compliqué
    // ATTENTION - ATTENTION - ATTENTION - ATTENTION - ATTENTION
    
    void test_pricing()
    {
      noeud n;
      
      // construit un objet du type phi1. pricing l'appelera grâce à son 
      // opérateur ()
      p.pricing(..., phi1(), ...);
    
      // on peut tout simplement lui passer un pointeur sur une fonction
      // ou un pointeur sur une fonction membre statique
      p.pricing(..., phi2, ...);
      p.pricing(..., X::phi3, ...);
    
      // avec un peu de courage, on peut aussi lui passer une fonction
      // membre d'une classe, mais il faut l'associer à une instance de 
      // cette classe. Il faut s'aider d'un objet intermédiaire pour transformer
      // le couple (Classe, fonction membre non statique) en foncteur classique. 
      // malheureusement, le standard C++ ne fournit pas un tel type, donc on
      // en a développé un nous-même - c'est la classe template phi_helper<>
      // ci-dessus. Puisqu'on veut se simplifier l'écriture au maximum, on va éviter 
      // d'instancier de manière explicite cette classe, et on va passer par une
      // fonction template (make_phi_helper<>()) qui va déduire toute seule un
      // certain nombre de choses.
      X x; // il faut définir une instance de X
      p.pricing(..., make_phi_helper(&x, &x::phi4),...);
    
      // encore plus fort, si la fonction phi à passer en paramètre est une
      // méthode de la classe noeud. Dans ce cas, le foncteur évalué se comporte
      // ainsi : 
      // phi(node, v) --> node->mbrfun(v)
      p.pricing(..., std::mem_fun_1(&noeud::phi5), ...);
    }
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  12. #12
    Membre expérimenté
    Avatar de Chatanga
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 211
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Il est toutefois possible de faire les choses un peu différemment, en passant par les templates. [...] Le code suivant est alors valide :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // cas phi1 : foncteur classique
    struct phi1
    {
      void operator()(noeud *const arbre, double v)
      { ... }
    };
    
    // ...
      
    // construit un objet du type phi1. pricing l'appelera grâce à son 
    // opérateur ()
    p.pricing(..., phi1(), ...);
    J'ai un peu regardé les sources de Boost (bind et function essentiellement) afin de comprendre comment ils s'en sortent pour faire la même chose sans template. Ma première conclusion, c'est que le "C++ moderne" peut être aussi hermétique que l'art moderne. Il me faudra plusieurs relectures pour vraiment comprendre "le truc".

  13. #13
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Boost.bind et boost.function sans template? hein?


    sans template variadique peut être?

  14. #14
    Membre expérimenté
    Avatar de Chatanga
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 211
    Par défaut
    Mon précédent message était ambigu. Il y a évidemment des templates dans les modules bind & function de Boost et ils permettent, entre autres,
    de passer un foncteur (tel 'phi1' au-dessus) comme paramètre d'une fonction non template requérant un simple pointeur sur fonction. Ce n'est pas simple et c'est pourquoi Emmanuel Deloget à du réécrire 'pricing' sous forme d'une fonction template pour illustrer ses propos.

  15. #15
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    C'est vrai que tu peux simplifier le code ci-dessus en décidant de passer un boost::function<void(noeud* const, double)> en paramètre (ou, pour rester dans le domaine de la norme, et puisque de nombreux compilateurs récents le supporte, std::tr1::function<void(noeud* const, double)>.

    De là à dire que ça ne nécessite pas de templates... Le code de boost.function est un peu plsu complexe à comprendre que celui que j'ai écrit ci-dessus
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  16. #16
    Membre expérimenté
    Avatar de Chatanga
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 211
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    De là à dire que ça ne nécessite pas de templates... Le code de boost.function est un peu plsu complexe à comprendre que celui que j'ai écrit ci-dessus
    Encore une fois, la seule chose que j'énonçais c'est que la méthode bind de Boost permet d'injecter un paramètre à une fonction non template. Boost et son module bind sont évidemment pleins à craquer de templates, mais pas la fonction recevant le paramètre et, ça, c'est fort.

    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
    typedef double (* PtrSurFonction) (double);
     
    double fonctionNonTemplate(PtrSurFonction f, double n) {
    	return f(n);
    }
     
    template< T >
    double fonctionTemplate(T f, double n) {
    	return f(n);
    }
     
    double phi(double k, double n) {
    	return k * n;
    }
     
    struct < template T >
    struct FoncteurPhi
    {
    	int k_;
     
    	FoncteurPhi(int k) : k_(k)
    	{}
     
    	double operator()(double n) {
    		return k * n;
    	}
    }
     
    int main(int, char **) {
    	// Marche.
    	fonctionTemplate(FoncteurPhi(5), 10);
     
    	// Ne compile évidemment pas !
    	// fonctionTemplate(phi(5), 10);
     
    	// Ne compile pas non plus !
    	// fonctionNonTemplate(FoncteurPhi(5), 10);
     
    	// Marche avec une FONCTION *NON* TEMPLATE !
    	fonctionNonTemplate(boost::bind(phi, _1, 5), 10);
    }

Discussions similaires

  1. [POO] Prototypes de fonctions et IE
    Par T.NightGlow dans le forum Bibliothèques & Frameworks
    Réponses: 9
    Dernier message: 15/01/2008, 16h50
  2. definition prototypes de fonctions dans main
    Par fantomas261 dans le forum C
    Réponses: 4
    Dernier message: 19/10/2007, 11h18
  3. Question sur les prototypes de fonctions
    Par GnuVince dans le forum Langage
    Réponses: 2
    Dernier message: 23/11/2006, 23h37
  4. .net prototype de fonction
    Par stgi02 dans le forum MFC
    Réponses: 1
    Dernier message: 13/04/2006, 22h41
  5. prototype de fonction ?
    Par salseropom dans le forum C
    Réponses: 3
    Dernier message: 07/04/2006, 10h01

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