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 :

Spécialisation de template et restriction des types


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 23
    Points : 18
    Points
    18
    Par défaut Spécialisation de template et restriction des types
    Bonjour,

    Je voudrais spécialiser une classe template pour un type particulier, tout en pouvant continuer à pouvoir spécifier le type du template.
    Je sais que ce n'est pas très clair, voilà ce que je cherche concrètement à faire :

    J'ai un classe abstraite XmlInterface qui représente des objets pouvant être stockés au format XML.
    Plusieurs classes hérites de XmlInterface, dont la classe ObservableList.

    La classe ObservableList hérite aussi de QList (le conteneur de Qt équivalent à std::list).
    Le but est de pouvoir stocker une liste d'objet au format XML.

    Pour ce faire j'ai spécialiser QList en QList<XmlInterface*> lors de la création de la classe ObservableList.

    Le problème est que lorsque j'instancie un objet de type ObservableList je ne peux pas spécifier le type des objets que je veux y stocker.

    J'aimerais donc savoir s'il est possible de restreindre le type des objets stockés au type XmlInterface et ses sous types tout en gardant "l'aspect" template ?

    Voici une simplification de mon code actuel :
    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
    class XmlInterface
    {
    	public :
    		virtual QDomDocument toXml() const = 0;
    		virtual bool fromXml(const QString& filePath) = 0;
    };
     
    class ObservableList : public QList<XmlInterface*>, public XmlInterface
    {
    	public :
    		QDomDocument toXml() const
    		{
    			QDomDocument domDoc;
     
    			foreach (const XmlInterface* element, *this)
    			{
    				domDoc.appendChild(element->toXml());
    			}
     
    			return domDoc;
    		}
    };
     
    class Product : public XmlInterface
    {
    	public :
    		QDomDocument toXml() const;
    };
     
    class Taskmaster : public XmlInterface
    {
    	public :
    		QDomDocument toXml() const;
    };
     
    int main(int argc, char *argv[])
    {
    	ObservableList products;	// Je voudrais ObservableList<Product*> products
    								// Pour que products.at(0) retourne un Product* et non un XmlInterface*
    }
    Pour parvenir au résultat en commentaire je ne dois pas spécialiser QList mais dans ce cas comment m'assurer que le type template utilisé ne correspond pas à autre chose qu'une classe dérivée de XmlInterface ?

    Merci d'avance, bonne journée.

  2. #2
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Je ne suis pas sûr pour les QList, mais pour les std::list, il est fortement déconseillé d’en hériter publiquement (elle n’est pas conçue pour, absence de destructeur virtuel notamment).

    Pour ta fonction toXml, elle pourrait très bien être une fonction libre travaillant sur une QList<XmlInterface*>

    Ensuite, je ne comprends pas très bien ton problème : une QList<Products*> contiendra toujours des Products* (ou dérivé), donc pas des XmlInterface*.

    J’ai un peu de mal à voir où tu veux en venir et je soupçonne fortement le défaut de conception derrière.

  3. #3
    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,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template <typename T> struct dummy{}; // (1) definition générique
    template <typename T> struct dummy<T*>{}; // (2) spécialisation partielle
    struct foo{};
    template struct dummy<foo*>{}; // (3) spécialisation pout foo*
     
        dummy<int> i; // 1 
        dummy<int*> pi; // 2
        dummy<foo> f; // 1
        dummy<foo*> pf; // 3
    [edit] : en général, les classes de type QList ne sont pas faites pour en être héritées publiquement. La composition est souvent préférable

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 23
    Points : 18
    Points
    18
    Par défaut
    Merci des réponses.

    Je ne savais pas qu'il était déconseillé d'en hériter...
    Je pense donc enlever l'héritage et créer un attribut privé de type QList.

    une QList<Products*> contiendra toujours des Products* (ou dérivé), donc pas des XmlInterface*
    Je suis d'accord. Mon problème était justement qu'en ayant spécialiser mon QList lors de la définition de ma classe je ne pouvais plus passer Product* en paramètre de template.

    De toute évidence c'est un problème de conception je voulais juste m'assurer qu'il n'y avais pas de possibilité de "filtrer" le paramètre template fournis.

    Bonne journée.

  5. #5
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    FAQ : Pourquoi le destructeur d'une classe de base doit être public et virtuel ou protégé et non virtuel ?

    Citation Envoyé par white_tentacle Voir le message
    Je ne suis pas sûr pour les QList, mais pour les std::list, il est fortement déconseillé d’en hériter publiquement (elle n’est pas conçue pour, absence de destructeur virtuel notamment).
    Citation Envoyé par 3DArchi Voir le message
    [edit] : en général, les classes de type QList ne sont pas faites pour en être héritées publiquement. La composition est souvent préférable
    Si seulement... http://qt.gitorious.org/qt/qt/blobs/...glist.h#line66

    (pour les débutants : "on ne fait pas d'héritage public sans destucteur virtuel".
    Pour les autres : en fait, ça ne pose pas de problème, tant que la classe dérivée ne contient pas de nouvelles variables membre, ce qui est le cas de QList. Pas de fuite mémoire)

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 053
    Points
    33 053
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    Pour les autres : en fait, ça ne pose pas de problème, tant que la classe dérivée ne contient pas de nouvelles variables membre, ce qui est le cas de QList. Pas de fuite mémoire)
    En fait la vraie raison est qu'il n'y a pas de souci tant qu'on ne manipule pas des B* comme étant des A* (la partie B ne serait pas supprimée à l'appel du destructeur.. de A).
    Ou on m'a menti toutes ces années ?
    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
    struct A {
     int a;
     int b;
     ~A() {}
    };
    struct B : A {
     int c;
     ~B() {}
    };
     
    B b;
    A a;
    B* bb = new B;
    A* aa = new A;
    A* ba = new B; // problème !
    B* ab = new A; // WTF ?!

  7. #7
    En attente de confirmation mail

    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 : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    <HS>
    In the first alternative (delete object), if the static type of the object to be deleted is different from its
    dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the
    static type shall have a virtual destructor or the behavior is undefined.
    (n3337 5.3.5 paragraphe 3)
    Dans le premier cas (delete object), si le type statique de l'objet à détruire est différent de son type dynamique, le type statique doit être une classe de base du type dynamique de l'objet à détuire et le type statique doit avoir un destructeur virtuel, sinon le comportement est indéfini.
    Débutant ou pas, Qt ou pas, ca peut conduire à un UB.
    </HS>

  8. #8
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    J'avais pas vu

    Citation Envoyé par Bousk Voir le message
    Citation Envoyé par gbdivers Voir le message
    Pour les autres : en fait, ça ne pose pas de problème, tant que la classe dérivée ne contient pas de nouvelles variables membre, ce qui est le cas de QList. Pas de fuite mémoire)
    En fait la vraie raison est qu'il n'y a pas de souci tant qu'on ne manipule pas des B* comme étant des A* (la partie B ne serait pas supprimée à l'appel du destructeur.. de A).
    Ou on m'a menti toutes ces années ?
    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
    struct A {
     int a;
     int b;
     ~A() {}
    };
    struct B : A {
     int c;
     ~B() {}
    };
     
    B b;
    A a;
    B* bb = new B;
    A* aa = new A;
    A* ba = new B; // problème !
    B* ab = new A; // WTF ?!
    Pas de problème pour ton code. Mais je parlais du cas où "tant que la classe dérivée ne contient pas de nouvelles variables membre" -> dans ce cas, le destructeur de la classe de base va correctement désallouer les variables membres de la classe de base et le destructeur de la classe dérivée n'a rien à faire
    Mais on est d'accord que c'est pas très propre, qu'il faut que celui qui écrit la classe dérivée ne fasse pas n'importe quoi, que la composition est préférable et que Qt n'est pas forcement un exemple à suivre (mais on trouve quand même ce type de code dans Qt)

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

Discussions similaires

  1. Réponses: 20
    Dernier message: 12/11/2014, 13h33
  2. Axis : Restriction des types dans le WSDL
    Par rockley dans le forum Services Web
    Réponses: 4
    Dernier message: 26/11/2012, 08h51
  3. Spécialisation de template pour le type tableau
    Par backlash dans le forum Langage
    Réponses: 4
    Dernier message: 11/09/2011, 09h09
  4. [Template] Déclaration des types template
    Par khaledbenamor dans le forum Langage
    Réponses: 2
    Dernier message: 18/11/2008, 09h56
  5. [ADO] Constantes des types de champ
    Par SpaceFrog dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 05/09/2002, 11h08

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