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 :

Templates : restreindre l'instanciation à une hiérarchie de types


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut Templates : restreindre l'instanciation à une hiérarchie de types
    Hello,

    Disons que j'ai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T>
    class tempClass
    {
       ...
    };
    Comment faire en sorte que tempClass ne soit instanciable qu'avec des types descendant du même parent (avec le parent lui-même), la hiérarchie étant construite via CRTP ?...

    Merci.

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 199
    Par défaut
    Corrigez moi si je me trompe, mais a tu regarde du cote de <type_traits> avec std/boost::is_base_of<Base, Derived>?

    Edit : Le tout couple avec une static_assert

    Doc boost de la classe, je me souvenais plus de l'odre des template! http://www.boost.org/doc/libs/1_48_0...s_base_of.html

  3. #3
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    ne serait-pas possible en déclarant ça comme abstraite et en implémentant que pour les types spécifiques nécessaires ?

    Exemple de ce que j'ai en tête:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template< class T >
    class tempClass
    {
     void doSomething()=0;
    };
    class Parent {};
    template<>
    class tempClass<Parent>
    {
     void doSomething() {}
    };
    Ce qui, si ça fonctionne comme je l'espère, entraînera une erreur de compilation avec autre chose qu'un Parent (ou dérivé), avec une errreur de "cannot instatiate abstract class".
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Bonjour,

    Pour cette dernière proposition, je crains fort que l'erreur de compilation survienne même avec les classe dérivées de « Parent »...

  5. #5
    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
    +1 à la réponse de victor_gasgas ; j'ajoute que les type traits ayant été intégré au TR1, il n'est pas nécessaire d'utiliser boost ou C++11 pour y avoir accès.

    Par contre, static_assert nécessite boost ou C++11 (mais on peut faire sans).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    template <class C, class P = Parent, bool defined = std::is_base_of<P,C> >
    class tempClass;
     
    template <class C, class P = Parent>
    class tempClass<C,P,true>
    {
    // ... le code de la classe
    }
     
    // pas de définition pour tempClass<C,P,false>, ce qui va provoquer 
    // une erreur à la compilation si C ne dérive pas de P.
    Ou quelque chose dans le style
    [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.

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Comment dois-je interpréter l'absence d'implémentation avec ta première déclaration de template ?

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par oodini Voir le message
    Comment dois-je interpréter l'absence d'implémentation avec ta première déclaration de template ?
    Justement, comme une déclaration de la classe template, et non comme sa définition

    On pourrait, en gros, dire qu'il s'agit d'une déclaration anticipée (en tout cas, c'est le terme connu qui s'en rapproche le plus ) permettant au compilateur de savoir que ta classe fonctionne avec "jusqu'à" trois paramètres template (les deux derniers ayant des type par défaut .

    Mets toi un instant à la place du compilateur, tu vas voir, le jeu est sympa

    En ligne 1 et 2, le compilateur apprend qu'il existe une classe nommée tempClass qui est une classe template prenant trois arguments, dont les deux derniers sont factulatifs (car on donne une valeur par défaut).

    Les arguments facultatifs disent que P est, à défaut d'indication contraire, de type Parent et que defined (le booléen) prend la constante renvoyée par is_base_of(P, C), c'est à dire true si la classe P est bel et bien d'un type de base de la classe C.

    Les lignes 5 à 9 fournissent une définition pour cette tempClass pour certains arguments template particulier, dont le fait que le booléen (defined ) vaut true, c'est à dire si le résultat de l'évaluation de is_base_of est bel et bien true

    De cette manière, si on vient à avoir un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class A
    {
        /* ...*/
    };
    class B : public A
    {
        /* ...*/
    };
     
    int main()
    {
        tempClass<B, A> temp;
    }
    is_base_of fournit bel et bien la constante true, vu que A est bien... la classe parent de B, et le compilateur trouve la définition de la classe correspondant à C = B, P = A, defined = true, et va donc l'utiliser (il n'y aura pas d'erreur de compilation )

    Par contre, si tu utilise le code
    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
    {
        /* ...*/
    };
    /* !! pas d'héritage publique de A !!! */
    class B 
    {
        /* ...*/
    };
     
    int main()
    {
        tempClass<B, A> temp;
    }
    Le compilateur trouve la déclaration de la classe template qui fonctionne avec les arguments fournis : C = B, P = A, defined = false.

    Jusque là, il est content

    Sauf que, quand il va rechercher le constructeur (par défaut ici ) de tempClass, il ne va pas le trouver, vu que la seule défintion qu'il trouve (et donc pour laquelle il existe bel et bien un constructeur par défaut (dans le cas présent) correspond aux argument C = B, P = A, defined = true, et que defined vaut... false

    Il va donc sortir avec une erreur de compilation proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    cannot find tempClass<C, P, defined>::tempClass() 
        [with C = B, P = A, defined  = false ]
    Et c'est exactement ce que tu voulais : tempClass ne peut pas être utilisée si tu ne fournis pas effectivement une classe dérivée et sa classe mère (ou ancêtre)
    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

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 09/02/2011, 15h40
  2. Réponses: 7
    Dernier message: 22/02/2007, 16h57
  3. [template] Instanciation d'une liste de types pour un plugin
    Par Matthieu Brucher dans le forum C++
    Réponses: 6
    Dernier message: 11/01/2007, 07h54
  4. Réponses: 13
    Dernier message: 25/10/2006, 16h17
  5. Réponses: 2
    Dernier message: 18/10/2003, 14h42

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