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 :

Classe template générique


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 24
    Points
    24
    Par défaut Classe template générique
    Bonjour à tous,

    J'ai encore quelques difficultés (si ce n'est beaucoup ) à comprendre les templates. Est-il possible, via ces derniers de créer une classe générique comme cela (la représentation est bien sur grossière) :

    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 A
    {
    template<typename U, typename V>map<U,V> list;
     
    template<typename U, typename V> void Add_Data(U key, V value) 
    { 
        list.insert(pair<U,V>(key,value));
    }
     
    template<typename U, typename V> V Get_Data(U key) 
    {
     return *(list.find(key));
    }
    }
    merci d'avance

  2. #2
    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 : 43
    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
    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
    template<typename U, typename V>
    class A
    {
    map<U,V> list;
     
    void Add_Data(U key, V value) 
    { 
    list.insert(pair<U,V>(key,value));
    }
     
    V Get_Data(U key) 
    {
    return *(list.find(key));
    }
    }
    est la bonne maniere

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 24
    Points
    24
    Par défaut
    Merci pour la rapidité de la réponse Joel !

    C'était à peu près ce que j'avais compris de l'histoire, je suis pas si nul que ca en fin de compte .
    Cependant, cela implique une autre problématique car pour utiliser cette classe A avec toutes les combinaisons de types <U,V>, il m'est nécessaire de devoir définir une nouvelle variable à chaque fois, ce qui est embêtant. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class B
    {
    private:
        A<bool,int> t1;
        A<string,bool> t2;// etc etc
     
    }
    Ce qui devient lourds si on doit gérer toutes les combinaisons.

    N'y-t-il pas un moyen de gérer ca avec une seule variable ? J'ai cru comprendre que boost::variant était une solution...

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,

    Il faut faire attention au fait que, lorsque tu crées une classe template et qu'elle n'hérite pas d'une classe de base qui ne serait pas template, une instance de type TaClass<A, B> n'a strictement rient à voire (hormis l'interface et le comportement) avec une instance de type TaClass<C, D>, ni même seulement avec une instance de type TaClass<A, C>...

    Ce que je veux dire par là, c'est que tu ne pourras absolument pas envisager de créer une collection d'objets qui contiendrait une instance de TaClass<A, B> et une instance de TaClass<C, D> .

    Le but des template est d'autoriser l'utilisation du paradigme dit "générique", c'est à dire un moyen qui te permettra d'écrire peu de code, mais de le faire s'adapter à de nombreuses situations quant aux types utilisés, pour autant que les types en question respectent une interface donnée.

    Si le but est, comme ta question semble le suggérer, de pouvoir profiter de la substituabilité des différents types, il faudra de toutes manière en arriver à avoir une classe de base commune, avec l'héritage qui va bien...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 24
    Points
    24
    Par défaut
    Au risque de paraitre têtu (désolé par avance koala01), j'ai essayé quelque chose. Ca en marche pas bien sur, sinon ca aurait été trop facile. Je veux juste saisir ce concept de template.

    Le Point.h
    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
     
    typedef boost::variant<int ,double> IType;
     
    class Point : public Coords
    {
    private:
        Datas<unsigned int,IType > idata;
    public:
        Point(const double _x, const double _y, const double _z);
        virtual ~Point(){}
        virtual string __ToString(const bool _parent=false) const;
        template<typename T> bool AddData(const unsigned int tag, const T t);
        template<typename T> const T &GetData(const unsigned int tag) const;
     
    };
    Le Point.cpp :
    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
    Point::Point(const double _x, const double _y, const double _z):Coords(_x,_y,_z)
    {
    }
     
        string Point::__ToString(const bool _parent) const
        {
        ostringstream oss;
        if (!_parent) oss << "########## COORDS ##########"<<endl;
        oss.precision(4);
        oss << "("<<_x()<<";"<<_y()<<";"<<_z()<<")"<<endl;
        return oss.str();
        }
       template<typename T> bool Point::AddData(const unsigned int tag, const T t)
     
        { idata.Add_Data(tag,t); return true;}
     
        template<typename T> const T & Point::GetData(const unsigned int tag) const
        {
    	idata.Get_Data(tag);
        }
    Le datas.h
    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
     
    #include <map>
    using namespace std;
    template<typename U, typename V>class Datas
    {
    private:
        map<U,V> list;
    public:
        Datas(){}
        void Add_Data(U key, V value)
        {
        list.insert(pair<U,V>(key,value));
        }
     
        V Get_Data(U key)
        {
        return *(list.find(key));
        }
     
        void Remove_Data(U key)
        {
    	list.erase(list.find(key));
        }
    };
    et le main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int main(){
        Point c(1,2,3);
        c.AddData(3, 2.1);
    }

    Pourquoi il me sort ca lors de la compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Undefined symbols:
      "bool ICMole::Point::AddData<double>(unsigned int, double)", referenced from:
          _main in main.o
    ...

  6. #6
    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 gilims Voir le message
    Pourquoi il me sort ca lors de la compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Undefined symbols:
      "bool ICMole::Point::AddData<double>(unsigned int, double)", referenced from:
          _main in main.o
    ...
    F.A.Q. : Pourquoi mes templates ne sont-ils pas reconnus à l'édition des liens ? . C'est aussi vrai pour les fonctions membres template d'une classe non template.


    Au passage :
    __ToString : Quels sont les identificateurs interdits par la norme ?

    Pas de using namespace dans un fichier d'en-tête F.A.Q: Quand utiliser / ne pas utiliser using namespace ?

    virtual string __ToString c'est très bof (ça sent le java à plein nez) La sérialisation en chaîne je n'aime pas trop l'avoir dans la classe. En plus ça sent la fonction d'un SuperObject duquel vont dériver tout tes objets. Bref, pas terrible d'un point de vue design

    class Point : public Coords J'ai du mal avec ça. A priori, Point (et Coords) ont une sémantique de valeur et non d'entité incompatible avec de l'héritage. Respectes-tu bien le LSP (héritage EST-UN) ? Ou les classes sont mal nommées ou le design est hasardeux.

    L'héritage se marie mal avec la copie. J'espère que Coords interdit la copie

    J'aurais mis typedef boost::variant<int ,double> IType; dans la classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     
    class Point : public Coords
    {
    typedef boost::variant<int ,double> IType;

  7. #7
    Membre régulier
    Homme Profil pro
    Développeur .NET/C/C++
    Inscrit en
    Septembre 2007
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET/C/C++
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2007
    Messages : 71
    Points : 122
    Points
    122
    Par défaut
    Plusieurs remarques:
    - Pour ta classe Data, je ne vois pas trop à quoi elle sert. Pour moi, tu peux utiliser une std::map directement.
    -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Undefined symbols:
      "bool ICMole::Point::AddData<double>(unsigned int, double)", referenced from:
          _main in main.o
    Pour info, ce n'est pas un problème à la compilation mais bien à l'édition de liens. C'est une erreur classique quand on apprend à utiliser les templates (je l'ai faite avant toi ) Voir la faq pour plus d'infos.

    (EDIT : grilled )

    - Ta variable idata va contenir des valeurs qui seront soit des entiers, soit des doubles, chaque valeur étant indéxée via un entier non signé. Est-ce bien là ce que tu veux faire?

    - Pour ton code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    12345678  
    class B
    {
    private:
        A<bool,int> t1;
        A<string,bool> t2;// etc etc
     
    }
    ce qu'il faut que tu comprennes, c'est que
    représente un type, et
    représente un autre type.
    Du coup, tes variables t1 et t2 sont bien de type différent, donc impossible de les stocker directement dans une même variable. L'utilisation de boost::variant peut effectivement aider, encore faut-il voir s'il s'agit bien de la solution la plus adaptée à ton problème.
    "Toujours en faire plus pour en faire moins"

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 24
    Points
    24
    Par défaut
    Désolé pour le retard dans ma réponse, vacance oblige !

    Merci bountykiler et 3DArchi pour vos réponses.

    Après avoir pris du recul avec ca, je comprends finalement que cette classe template générique ne sert à rien !!

    class Point : public Coords J'ai du mal avec ça. A priori, Point (et Coords) ont une sémantique de valeur et non d'entité incompatible avec de l'héritage. Respectes-tu bien le LSP (héritage EST-UN) ? Ou les classes sont mal nommées ou le design est hasardeux.
    J'ai aussi du mal avec ca !! Ils ont une sémantique d'entité et non de valeur (en tout cas je pense). La raison est que j'utilise ca pour des atomes, donc si je suis le faq, deux atomes ayant les mêmes coordonnées, (même si c'est impossible), reste deux atomes différents n'est-ce pas ?

    __ToString : Quels sont les identificateurs interdits par la norme ?
    Pas de using namespace dans un fichier d'en-tête F.A.Q
    virtual string __ToString
    L'héritage se marie mal avec la copie. J'espère que Coords interdit la copie
    Coords interdit en effet la copie. Mais si j'ai besoin de copier un atome (car je copie la molécule par exemple), cela est-il faisable via une sémantique d'entité et de l'héritage ?

    Pour les templates, je vais encore m'entrainer !!

  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 gilims Voir le message
    Ils ont une sémantique d'entité et non de valeur (en tout cas je pense). La raison est que j'utilise ca pour des atomes, donc si je suis le faq, deux atomes ayant les mêmes coordonnées, (même si c'est impossible), reste deux atomes différents n'est-ce pas ?
    Atome a effectivement une sémantique d'entité mais sa position a une sémantique de valeur
    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
     
    struct Position
    {
    // ....
    };
    bool operator==(Position const&lhs, Position const&rhs);
    bool operator!=(Position const&lhs, Position const&rhs);
    bool operator+(Position const&lhs, Position const&rhs);
    // etc...
     
    class Atom
    {
    public:
    virtual ~Atom(); // si utilisé comme base d'héritage
    private:
    Atom(Atom const&); // = delete
    Atom&operator=(Atom const&); // = delete
     
    Position pos;
    }
    Citation Envoyé par gilims Voir le message
    Coords interdit en effet la copie. Mais si j'ai besoin de copier un atome (car je copie la molécule par exemple), cela est-il faisable via une sémantique d'entité et de l'héritage ?
    Normalement tu ne fais pas une copie mais tu créés une nouvelle instance d'atome démarrant avec un état identique... C'est en général fait avec un design pattern Prototype
    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
    #include <memory>
     
    class Atom
    {
    public:
       Atom(){}
       virtual ~Atom(); // si utilisé comme base d'héritage
     
     
       std::shared_ptr<Atom> Clone()
       {
          return std::shared_ptr<Atom>(do_Clone());
       }
     
    private:
       virtual Atom* do_Clone()
       {
          return new Atom;
       }
     
       Atom(Atom const&); // = delete
       Atom&operator=(Atom const&); // = delete
     
       Position pos;
    };
     
    class TelAtom : public Atom
    {
    public:
       TelAtom(){}
     
    private:
       TelAtom* do_Clone()
       {
          return new TelAtom;
       }
    };

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 24
    Points
    24
    Par défaut
    Magnifique !! J'ai mis en place ce système et ca marche du tonnerre !!
    J'ai tenté de coupler ca avec des pointeurs intelligents à partir du lien sur les designs patterns et ca marche. Difficile à mettre en place la première fois mais c'est nickel !!
    J'ai aussi réaliser quelques essais avec des fonctions templates, et ca fonctionne ... que demande le peuple !!

    Par contre, j'ai un autre concept à mettre en place, sur le même principe et sur lequel j'aimerais avoir l'avis du forum (et le tien/votre ?). J'ouvre un autre post ou je le mets ici ?

    En tout cas merci encore 3DArchi

  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 gilims Voir le message
    J'ouvre un autre post ou je le mets ici ?
    Nouvelle question, nouveau fil de discussion

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

Discussions similaires

  1. Classe Liste générique avec template
    Par TNT89 dans le forum Langage
    Réponses: 9
    Dernier message: 09/05/2009, 15h14
  2. [DLL/classe template] problème de link
    Par Bob.Killer dans le forum C++
    Réponses: 7
    Dernier message: 31/08/2005, 18h56
  3. Class template hérité
    Par Azharis dans le forum Langage
    Réponses: 4
    Dernier message: 24/06/2005, 22h03
  4. Réponses: 6
    Dernier message: 06/10/2004, 12h59
  5. classe date générique ?
    Par lili_bzh dans le forum Décisions SGBD
    Réponses: 1
    Dernier message: 07/09/2004, 10h59

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