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 :

[C++] Créer une fonction template avec argument


Sujet :

C++

  1. #1
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut [C++] Créer une fonction template avec argument
    Bonsoir,

    J'ai défini des classes qui possèdent toute une méthode afficher(param p).

    Etant donné que j'utilise des std::vector, j'ai eu l'idée de créer une fonction template pour appeller la fonction afficher(param p) quelque soit la classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct Afficher
    {
        /*Afficher(const BITMAP*& zoneJeu) zoneJeu(zoneJeu) {}*/
       template <class T> void operator ()(T*& p, BITMAP* zoneJeu) const
       {
          p->afficher(zoneJeu);
       }
    /*
       private:
        BITMAP* zoneJeu;*/
    };
    Et l'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for_each(tabVector.begin(), tabVector.end(), Afficher(zoneJeu));
    Message d'eereur :
    no matching function for call to `Afficher::Afficher(BITMAP*&)'|
    Ca ne fonctionne pas, j'ai testé des variantes en commentaire.

    Le but est de remplacer des fonctions du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    for (unsigned int i=0; i<tab1.size(); i++)
        {
            tab1[i]->afficher(zoneJeu);
        }
    for (unsigned int i=0; i<tab2.size(); i++)
        {
            tab2[i]->afficher(zoneJeu);
        }
    Voilà merci et bonne soirée

  2. #2
    la_tupac
    Invité(e)
    Par défaut
    Salut, il me semble ce que tu essaye de faire c'est un overload du constructeur, non? Je ne suis pas un pro mais je crois aussi qu'il est impossible de procéder ainsi.
    Je peux me tromper mais le p->afficher() n'aura pas la même valeur en tant que pointeur de fonction si la class est diférente.
    Perso j'utilise dynamic_cast avec diférents types et si le retour est non null je place l'appel à p->afficher(). C'est surement un peu lourd mais ça fonctionne .

  3. #3
    Membre chevronné
    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 : 44
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    tupac, non, encore heureux qu'on puisse surcharger le ctor ..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct Afficher
    {
        Afficher(const BITMAP*& zoneJeu) : zoneJeu(zoneJeu) {}
       template <class T> void operator ()(T*& p, BITMAP* zoneJeu) const
       {
          p->afficher(zoneJeu);
       }
     
       private:
        BITMAP* zoneJeu;
    };
    devrait fonctionner. Je pense que tu avais oublier le : dans la liste d'initialiation.

    Donnes quand meme le code de afficher et des classes stockées dans ton vector.

  4. #4
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    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
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Joel F Voir le message
    tupac, non, encore heureux qu'on puisse surcharger le ctor ..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct Afficher
    {
        Afficher(const BITMAP*& zoneJeu) : zoneJeu(zoneJeu) {}
       template <class T> void operator ()(T*& p, BITMAP* zoneJeu) const
       {
          p->afficher(zoneJeu);
       }
     
       private:
        BITMAP* zoneJeu;
    };
    devrait fonctionner. Je pense que tu avais oublier le : dans la liste d'initialiation.

    Donnes quand meme le code de afficher et des classes stockées dans ton vector.
    Pourquoi est-ce que l'operator() prends deux arguments ? for_each() appelle le functor avec un seul argument, donc ça ne pourra pas marcher.

    Ensuite, passer une référence sur un pointeur, ce n'est pas utile - d'autant que le pointeur n'est pas modifié dans la fonction.

  5. #5
    Membre chevronné
    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 : 44
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    effectivement, j'ai juste corrigée l'erreur sur le liste d'init. Ca m'apprendra a posté a 7h14 :E

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct Afficher
    {
        Afficher(const BITMAP*& zoneJeu) : zoneJeu(zoneJeu) {}
       template <class T> void operator ()(T const& p) const
       {
          p.afficher(zoneJeu);
       }
     
       private:
        BITMAP* zoneJeu;
    };

  6. #6
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Exact ca marche

    J'avais vu l'erreur dans le foncteur ce matin mais j'ai oublié de posté la solution

    Cependant juste une question : Quel est l'intérêt d'utiliser des foncteurs plutôt que d'utiliser des for ? Est ce que c'est plus performant ?

    Merci !

  7. #7
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    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
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Aspic Voir le message
    Exact ca marche

    J'avais vu l'erreur dans le foncteur ce matin mais j'ai oublié de posté la solution

    Cependant juste une question : Quel est l'intérêt d'utiliser des foncteurs plutôt que d'utiliser des for ? Est ce que c'est plus performant ?

    Merci !
    C'est plus générique. C'est tout. La question de la performance ne se pose que lorsqu'un problème de performance est identifié. Là, tu gagnes de l'ordre de 0,000 millisecondes à l'exécution. En nanosecondes, il y a peut-être une différence.

    Parmi les gains notables, le fait de déplacer le traitement dans un foncteur permet de:

    1) paramétrer l'opération effectuée dans le boucle, sans pour autant faire de test. Le code est plus générique.
    2) externaliser cette opération. Le code n'étant plus local la fonction est plus courte à lire, à debugger, etc. Le code est plus maintenable.
    3) utiliser un algorithme générique, vérifié et revérifié par d'autres, pour le parcours de la boucle. Le code est plus robuste.

    La généricité apportée permets en outre de changer le comportement de la boucle sans changer la boucle elle-même. On évite ainsi les risques de régression qui pourraient être liées à une petite erreur dans la mise à jour du code.

    Bref, c'est beaucoup de bénéfice.

    Au niveau du code lui même : il y a de grandes chances que for_each() soit inliné, de même que le code su foncteur. Au final,le codé généré sera au pire identique à celui qui aurait été généré si tu avais écrit (correctement) la boucle.

    Donc pour résumer : tu n'y perds rien, et tu y gagne beaucoup : )

  8. #8
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    parfait réponse très clair

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Citation Envoyé par Emmanuel Deloget Voir le message
    Parmi les gains notables, le fait de déplacer le traitement dans un foncteur permet de:

    1) paramétrer l'opération effectuée dans le boucle, sans pour autant faire de test. Le code est plus générique.
    2) externaliser cette opération. Le code n'étant plus local la fonction est plus courte à lire, à debugger, etc. Le code est plus maintenable.
    3) utiliser un algorithme générique, vérifié et revérifié par d'autres, pour le parcours de la boucle. Le code est plus robuste.
    Souvent le foncteur est quand même une 'obligation' pour avoir un objet callable qu'un réel besoin de design. A ce titre les lambdas permettent de 'relocaliser' le traitement effectif d'un algo générique en évitant la multiplication des petits objets foncteurs.
    Par exemple, ici, Afficher est probablement appelée à un moment où on veut afficher et pas faire autre chose. Donc le foncteur n'est probablement pas un point de variation de la fonction. Et si on pouvait s'en passer, ce ne serait que mieux, non ?

  10. #10
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Bonjour,

    En fait je possède plusieurs classes avec toute une fonction afficher().
    Et j'ai aussi plusieurs vector de ses classes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    vector<class1*> tab1;
    vector<class2*> tab2;
    Et au début je faisais toujours le même boucle pour parcourir mes objets et les afficher:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for (unsigned int i=0; i<tab1.size(); i++)
        {
            tab1[i]->afficher(zoneJeu);
        }
    Pourquoi le foncteur ne serait-il pas adapter dans mon cas ?

  11. #11
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Aspic Voir le message
    Pourquoi le foncteur ne serait-il pas adapter dans mon cas ?
    Je réagissait plus à l'intervention d'Emmanuel qui à mon sens pouvait être comprise de façon trop générale. Pour ton problème, le foncteur explicite, mais aussi les lambdas ou des boost.bind (qui sont des aides à construire des foncteurs) avec un algo générique de type std::for_each parait approprié. Mais l'objet foncteur est ici ce qui te permet de créer un objet callable (on peut appliquer l'opérateur ()) avec un contexte (ici, l'appel avec this). Le foncteur ne crée pas un élément de design intéressant en soi. Dans les fonctions où tu fait ton std::for_each avec ton foncteur, le foncteur ne sera jamais amené à changer (alors que les implémentations de afficher() probablement que oui).

  12. #12
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Je réagissait plus à l'intervention d'Emmanuel qui à mon sens pouvait être comprise de façon trop générale.
    Oki

    Je ne pensais pas que le C++ était aussi compliqué il y a tellement de possibilité pour un problème donnée. Je ne connais pas encore les lambdas mais j'irais me renseigner.

    Merci

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

Discussions similaires

  1. Surchargé une fonction template avec template
    Par SKone dans le forum Langage
    Réponses: 2
    Dernier message: 12/10/2014, 20h00
  2. [E-00][VBA] Créer une fonction et ses arguments
    Par tiyolx dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 05/07/2013, 09h43
  3. Créer une fonction SQL avec variable
    Par theuma dans le forum Access
    Réponses: 6
    Dernier message: 18/04/2011, 12h02
  4. Réponses: 9
    Dernier message: 24/03/2011, 21h54
  5. Réponses: 3
    Dernier message: 13/04/2010, 16h13

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