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 :

Problème de template associés à des pointeurs de fonction


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Par défaut
    Bonjour à tous ,

    je suis nouveau sur ce forum, j'ai 15 ans et j'ai un problème concernant les templates et les pointeurs de fonction. Je dois avouer que je maîtrise (très) mal les templates mais les quelques recherches que j'ai effectuées ne m'ont pas permis de résoudre mon problème (ou d'une manière beaucoup trop complexe). Je compile sous windows 64bits avec code blocks et mingw meme si cela n'a pas beaucoup d'importance.

    Je développe actuellement un "éditeur" de boutons (correspondant à la classe Object et ses dérivés) en C++ avec la SFML qui devraient pouvoir être interconnectés avec toutes les variables du programme (ou une grande partie) sous forme de pointeurs de fonction : par exemple, une barre peut être connectée à la composante r de la couleur d'un autre objet, un bouton peur être connecté à l'affichage ou non d'un autre objet, un peu à la manière de Qt...

    Je dispose d'une classe centrale qui gère les évènements et le temps en les "redirigeant" vers tous les éléments (ou objets) sous forme de pointeurs de fonction. Le problème est que toutes les fonctions "setter" de toutes les classes présentent de nombreuses différences de patron : il y en a 7 pour l'instant. Le problème est que :

    -toutes les fonctions ne peuvent pas être "activées" (seules celles dont le patron est l'un des 7 patrons définis dans les pointeurs de fonction peuvent l'être)

    -le nombre de fonction pour changer les arguments passés aux fonctions lors de leur activation est multiplié par le nombre de patrons (7).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
            typedef void (MainWindow::*MainWindow_ptrColor)(sf::Color); //pointeur de fonction de MainWindow parametrant une couleur (donc SetColor)
            typedef void (MainWindow::*MainWindow_ptrInt)(int, bool); //pointeur de fonction de MainWindow parametrant une variable entiere
     
            typedef void (Object::*object_ptrFloat)(float, bool); //pointeur de fonction d'objet parametrant une variable flottante
            typedef void (Object::*object_ptrInt)(int, bool); //pointeur de fonction d'objet parametrant une variable entière
            typedef void (Object::*object_ptrString)(std::string); //pointeur de fonction d'objet parametrant un std::string
            typedef void (Object::*object_ptrVoid)(void); //pointeur de fonction d'objet déclenchant une fonction sans paramètre (comme par exemple Move)
            typedef void (Object::*object_ptrColor)(sf::Color); //pointeur de fonction d'objet parametrant une couleur
    Cependant, ce n'est pas du tout pratique car il faut que, pour chaque type de pointeurs, je crée les fonctions utiles pour travailler avec, ce qui multiplie par 7 (le nombre de pointeurs de fonction différents) le nombre de ces fonctions. Dans l'idéal, je voudrais obtenir quelque chose comme ce code qui ne marche pas pour remplacer les 7 pointeurs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
            template <typename T>
            typedef void (MainWindow::*MainWindow_ptrColor)(T,bool);
            template <typename T>
            typedef void (MainWindow::*MainWindow_ptrColor)(T);
            template <typename T>
            typedef void (Object::*MainWindow_ptrColor)(T,bool);
            template <typename T>
            typedef void (Object::*MainWindow_ptrColor)(T);
    erreur du compilo mingw sous code blocks :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    D:\mes documents\SFML\AllButtonsTest - Copie\mainwindow.hpp:19: error: template declaration of `typedef'
    D:\mes documents\SFML\AllButtonsTest - Copie\mainwindow.hpp:21: error: template declaration of `typedef'
    (il y a aussi d'autres erreurs mais qui sont liées à celles ci)

    Ou, encore mieux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
            template <typename T,typename S>
            typedef void (S)(T,bool);
            template <typename T>
            typedef void (S)(T);
    Je ne sais pas du tout comment faire ! Si vous n'avez pas très bien compris, je peux vous réexpliquer (ce qui m'est difficile )

    Merci d'avance pour votre aide !

  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
    Le problème est bien posé mais malheureusement pour toi, loin d'être trivial en l'état actuel.

    Avant de répondre directement, as tu regardé boost::function ou std::function (si ton compilo gère C++2011) pour voir s'il y avait moyen de retirer tout ce frattra de template. Tu peux même regarder boost::signal2 qui pourrait répondre à tes besoins (émettre des signaux entre des objets).

    Sinon, en l'état actuel de ton problème , je partirais dans la méta programmation [référence à ce sujet] ce qui risque de beaucoup augmenter la complexité de ton code.

    J'ai pas le temps d'essayer d'écrire un proof of concept mais à coup de typelist et macro ca doit se faire. En début de piste est l'utilisation de cette macro:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define foo(C,type) typedef void (C::*C##type)(type t); \
                                  typedef void (C::*C##type##b)(type t,bool);
    Après, en faisant varier C et type dans des typelist, y'a moyen de générer tout ca automatiquement.

    PS/ 15 ans, tu débutes en C++ et tu veux déjà toucher aux templates ? Tu me rappelles moi il y'a .... 5 ans de cela
    "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 éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Par défaut
    Tout d'abord merci de m'avoir répondu

    Je ne me suis encore jamais intéressé à la librairie boost et je ne sais pas si je vais l'utiliser car comme tu le dis cela risque d'augmenter la complexité du code et j'ai peur de ne pas comprendre ce que j'écrirai Je pense donc rester sur ce que j'ai fait même si cela demeure trop peu "modulable" mais je vais cependant m'intéresser de plus près à la métaprogrammation et je vais essayer d'utiliser la librairie boost
    Je vous tiens au courant

    Edit : Au fait pourrais tu m'expliquer un peu plus en détail la belle macro que tu me donnes en exemple, j'avoue avoir du mal a la comprendre

  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 Lintel-oo Voir le message
    Je ne me suis encore jamais intéressé à la librairie boost et je ne sais pas si je vais l'utiliser car comme tu le dis cela risque d'augmenter la complexité du code et j'ai peur de ne pas comprendre ce que j'écrirai
    La meilleure des compétences a avoir est celle qui consiste a savoir ne pas reinventer la roue. Boost, c'est comme std, ca s'apprend, ca se maitrise et ca s'exploite. Y a rien de "trop compliqué", sinon fallait faire du mecano

  5. #5
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 502
    Par défaut
    Je suis impressionné, à 15 ans, utiliser des templates, c'est déconcertant.

    Très peu de développeur débutant (après un bac+5 ) savent correctement s'en servir.

    Mais, notre orgueil de vieux programmeur est sauf.
    Putai*, Je terminais mes études qu'il ne savait pas encore marcher.

    Bon, la réponse est on ne peut plus simple :

    MSDN:

    Compiler Error C2823

    Send Feedback
    Error Message
    a typedef template is illegal


    Templates are not allowed in typedef definitions.

    The following sample generates C2823:

    // C2823.cpp
    template<class T>
    typedef struct x {
    T i; // C2823 can't use T, specify data type and delete template
    int i; // OK
    } x1;
    Oui, oui pas de template pour les typedef, mais c'est logique.

    Votre mode d'utilisation de ce template ne me semble pas clair.
    Si c'est pour économiser des copier-coller, les MACRO sont bien plus simples.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define TUTU(x) typedef void (__thiscall (##x)::*fn_float_##x )(float a, bool);typedef void (__thiscall (##x)::*fn_int_##x )(int a, bool)

  6. #6
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Si ton compilateur les supporte il y a les alias template (ou template typedef) du C++2011 qui pourrait peut-etre (*) résoudre ton problème. Regardes ici : http://www2.research.att.com/~bs/C%2...template-alias

    (*) Je n'ai jamais testé (marche pas sur mon compilateur) donc je ne peux pas garantir que dans ton cas ca marche. Je pense que la syntaxe serait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    template<class T>
    using ptr_func = void (*)(T);
    Mais je n'en suis pas certain.

  7. #7
    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
    Par défaut
    Salut,
    Sinon, tu peux passer par une structure pour définir les types :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    template <typename T>
    struct mes_traits
    {
            typedef void (MainWindow::*MainWindow_ptrColor)(T);
            template <typename T>
            typedef void (MainWindow::*MainWindow_ptrInt)(T, bool);
    };
    Séances lecture :
    Présentation des classes de Traits et de Politiques en C++ par Alp Mestan
    La métaprogrammation en C++ par Laurent Gomila
    Template rebinding en C++ par Alp Mestan

  8. #8
    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
    Double post avec celui ci Il faudrait les fusionner.
    "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)

  9. #9
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Par défaut
    Merci à tous , je vais regarder tout cela !

    double post avec celui ci Il faudrait les fusionner
    Comment fusionner les post ?

    Edit : ah non je crois que ça a été fait automatiquement

  10. #10
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Par défaut
    J'ai résolu une partie du problème , en mettant les pointeurs de fonction template dans une classe. J'y ai ajouté également une fonction qui permet d'ajouter des éléments à un std::vector :

    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
     
    template <typename T, typename S>
    class function_pointer_table_time
    {
        public:
            typedef void (S::*ptr)(T);
            typedef void (S::*ptr2)(T, bool);
     
            template <typename U, typename V>
            void add_element_ptr(U type, V parameter)
            {
                m_ptr.push_back(type,parameter);
            }
     
        private:
            std::vector<ptr> m_ptr;
            std::vector<T> m_parameter;
            std::vector<float> m_time;
            std::vector<float> m_current_time;
    };
    Cependant, comme vous pouvez le constater, la classe possède un template générique , donc tout ce qui est contenu dans le vector est finalement du meme type. Je sais que je n'arriverai pas facilement à obtenir quelque chose comme ça (je sais pourquoi ça plante mais je voudrai obtenir un résultat équivalent) :

    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
     
     
    class function_pointer_table_time
    {
        public:
            template <typename T, typename S>
            typedef void (S::*ptr)(T);
            template <typename T, typename S>
            typedef void (S::*ptr2)(T, bool);
     
            template <typename U, typename V>
            void add_element_ptr(U type, V parameter)
            {
                m_ptr.push_back(type,parameter);
            }
     
        private:
            std::vector<ptr> m_ptr;
            std::vector<T> m_parameter;
            std::vector<float> m_time;
            std::vector<float> m_current_time;
    };
    dans lequel je pourrai ajouter n'importe quel type de pointeur. Où dois-je chercher pour avoir quelque chose qui ressemble à ceci ? Dans les classes de traits ? de politiques ? Ou bien est-ce impossible ? En tout cas j'aurai appris déjà beaucoup de chose sur les templates grâce à vous

    Edit : après de nouvelles recherches, il semblerait que ce soit le genre de cas idéal pour le template rebinding. Je vous tiens au courant

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

Discussions similaires

  1. [JOGL] - equivalent des pointeurs sur fonction
    Par sir_gcc dans le forum OpenGL
    Réponses: 2
    Dernier message: 12/01/2009, 20h26
  2. Réponses: 1
    Dernier message: 07/11/2007, 10h06
  3. problème char-actéristique avec des pointeurs
    Par Antigonos Ier Gonatas dans le forum C
    Réponses: 11
    Dernier message: 16/04/2007, 21h22
  4. Transtypages sur des pointeurs de fonction
    Par gege2061 dans le forum GTK+ avec C & C++
    Réponses: 5
    Dernier message: 05/01/2007, 15h01
  5. [Language]Equivalent Java des pointeurs de fonctions du C/C++
    Par Thierry Chappuis dans le forum Langage
    Réponses: 1
    Dernier message: 25/11/2005, 15h14

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