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 :

spécialisation de modèle de classe


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut spécialisation de modèle de classe
    Bonjour,

    Je suis en train d'écrire une classe modèle, que je souhaite pouvoir spécialiser.
    Je suis sous QTCreator (MinGW 5.3.0 32) avec C++17 activé (config += C++17).

    EnumType.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
    template <typename Enum> // Classe de contenu
    struct EList { Enum val; std::string str; };
     
    template <typename Enum, class EnumList/*=EList<Enum>*//* retiré car un moment j'ai cru que c'était la cause*/>
    class TEnumType // classe modèle visée
    {
    ...
    protected:
        static const std::vector<EnumList> liste;
    ...
    };
     
    // pour les tests
    template <typename Enum>
    using TEnumTypeDef = class TEnumType<Enum,EList<Enum>>;
    user.h(module utilisateur)
    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
    //---------------------------------------------------------------------------
    enum class EType : int { ... };
    //---------------------------------------------------------------------------
    class TEnregistrement; // forward...
    struct tt { EType t; string str; const TEnregistrement *base; };
    // Spécialisation de EnumType pour EType et tt, introduisant une fonction nouvelle
    template<> class TEnumType<EType,tt>
    {
    public:
        static string CommaTypes(){
           // faire un truc... et renvoyer une chaine
        }
    };
    //---------------------------------------------------------------------------
    // Fonction pour tester le tout.
    void f() {
     
    TEnumTypeDef<EType> test2;
    decltype(test2)::liste; // Message indiquant que liste est protégé (fait exprès pour avoir ce message)
    TEnumType<EType,tt> test;
    decltype(test)::liste;  // Ici, message indiquant que liste n'est pas déclaré !?!.
    }
    //---------------------------------------------------------------------------
    Message modifié assez lourdement.. Veuillez m'en excuser si vous m'avez déjà lu... Tout était faux.
    En fait, la spécialisation de mon template se conduit comme si je créais une nouvelle classe... Je n'ai pas trouvé cela dans les docs (pour moi spécialisation signifie modifier certaines parties, mais pas tout annuler).
    Devrais-je donc faire un copier/coller de tous les éléments de ma classe modèle que je souhaite garder(pas très pratique tout ça)?
    Aurais-je commis une bourde quelque part?
    Ce comportement peut-il être vu avec d'autres compilateurs, ou bien est-ce lié à ma version?
    Toute information est la bienvenue,
    par avance merci à ceux qui auront eu le courage de me (re)lire!

    A bientôt!

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Une spécialisation c'est ce que doit être la classe modèle dans un cas particulier. C'est une classe qui n'a rien en commun avec son modèle hormis sa signature.
    Il faut donc entièrement définir la spécialisation.
    On peut quand même utiliser l'héritage (qui lui ne nécessite pas de redéfinition); On créé une classe "tronc-commun" (qui peut être un modèle); la classe modèle et les classes spécialisées devant hériter de ce tronc commun.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut
    Merci pour la réponse
    Néanmoins, je ne comprends pas trop l'utilité de la spécialisation dans ce cas, ma classe modèle a environ 40 membres, dans ma spécialisation, je souhaite juste en rajouter un... Pas confortable si je dois complètement la réécrire! Je ne souhaite pas utiliser l'héritage en raison des problèmes de covariance.
    A bientôt!

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut
    Je reviens un peu sur ma problématique pour expliquer ma perplexité :
    Il est vrai que ce que j'expose ressemble à un problème d'héritage.
    Cependant, ce qu'expose mon modèle est un groupe de types différents.
    Il est connu sous le nom EnumType<typename,classe> dans mon cas.
    Si, pour spécialiser un exemplaire de ces types j'utilise l'héritage, j'aurais les mêmes fonctionnalités, mais exposées sous un nom différent (signifie que je ne pourrai plus utiliser le nom de mon modèle dans d'autres modèles).
    De plus cela ne masquera pas ma classe de base. Je perds donc la cohérence du nommage, avec les erreurs qui peuvent y être liées.
    L'autre inconvénient de l'héritage est que je suis de toutes manières obligé de surcharger tous les membres renvoyant un objet de la classe par référence pour le transtyper convenablement...
    Je vais donc être obligé de la réécrire. Et pour me garder de soucis de maintenance (je suis très paresseux), la partie à reprendre sera réécrite sous la forme d'une macro.
    Cela pose également une autre question : qu'en serait-il si quelqu'un décidait de spécialiser une ou des classes std genre vector par exemple?
    Que d'écriture inutile, juste pour se conformer au standard...

    Encore merci pour la réponse

  5. #5
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Citation Envoyé par Teaniel Voir le message
    Si, pour spécialiser un exemplaire de ces types j'utilise l'héritage, j'aurais les mêmes fonctionnalités, mais exposées sous un nom différent (signifie que je ne pourrai plus utiliser le nom de mon modèle dans d'autres modèles).
    Non, l'héritage serait un détail d'implémentation que l'extérieur ne voit jamais et n'a pas besoin de connaître. Il n'est là que pour la spécialisation

    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
     
    namespace detail {
      struct Base
      {
        int i;
      };
    }
     
    template<class T>
    struct xxx : detail::Base
    {
      using detail::Base::Base;
    };
     
    template<>
    struct xxx<yyy> : detail::Base
    {
      using detail::Base::Base;
      int x;
    };
    De plus cela ne masquera pas ma classe de base. Je perds donc la cohérence du nommage, avec les erreurs qui peuvent y être liées.
    En quoi est-ce gênant ? Je ne comprends pas.

    L'autre inconvénient de l'héritage est que je suis de toutes manières obligé de surcharger tous les membres renvoyant un objet de la classe par référence pour le transtyper convenablement...
    Pour les problèmes de covariance on utilise généralement le CRTP (voir la FAQ). Ou des fonctions libres. Ou un wrappeur qui s'occupe de faire les retours.
    Tu peux aussi faire l'inverse et ajouter une base vide qui peut être spécialisé.

    Je vais donc être obligé de la réécrire. Et pour me garder de soucis de maintenance (je suis très paresseux), la partie à reprendre sera réécrite sous la forme d'une macro.
    Je vois mal le bénéfice apporté par les macros.

    Cela pose également une autre question : qu'en serait-il si quelqu'un décidait de spécialiser une ou des classes std genre vector par exemple?
    S'il spécialise, il l'a réécrit entièrement. Mais il y a suffisamment de point de variation pour ne pas le faire. Et généralement c'est par paresse pour ajouter des comportements sur un vector qui n'est pas qu'un vector. Dans ce cas, une composition ou un héritage privé avec l'importation des fonctions membres qui vont bien sont des meilleures solutions.

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut
    Bonjour,

    Finalement, tes remarques m'ont fait réfléchir :
    Concernant l'héritage, en fait je ne dois pas l'utiliser, car ce que je souhaite réaliser est un ensemble de types, fonctionnant (à peu près) de la même manière, mais qui n'ont rien d'autre en commun (deux enum class sont des types totalement différents, même s'ils peuvent avoir un type sous-jacent identique).
    De plus, si je l'utilise je perds la faculté d'utiliser ce que j'ai spécialisé dans un mécanisme générique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     template <typename t> TAutreModele<TEnumType<t>> ...
    appliqué à int génèrera le modèle de base et non le spécialsé (et alors même un transtypage ne fonctionnera pas). C'est ce que je voulais (mal) dire plus loin.
    S'il spécialise, il l'a réécrit entièrement.
    Ok. D'accord pour ce qui concerne vector... Pas le meilleur exemple.
    Dommage quand même, je trouve qu'il serait utile de ne pas être obligé de réécrire complètement un modèle (dans mon cas le fichier dans lequel il est décrit pèse près de 2000 lignes) juste pour en modifier quelques unes. Dans mon cas j'ai pu 'remonter' ce que je voulais y mettre dans le modèle de base, ce qui résout mon problème.
    Cela dit, je me trouve confronté à cela car je suis en train de reprendre un code vieux de 25 ans, écrit avec ce que je savais de l'époque, pour lequel tout était fait par macros (les génériques n'existaient pas), macros que je suis en train d'essayer de convertir en modèles.
    Merci aussi de m'avoir signalé le modèle CRTP, que je comprends mieux maintenant (tu auras compris je suppose que je ne suis pas développeur professionnel).
    A bienôt!

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 22/04/2013, 12h07
  2. Problème modèle et classe lier
    Par obarator dans le forum Visual Studio
    Réponses: 1
    Dernier message: 05/07/2011, 16h07
  3. Problème création modèle de classe + Oracle datasource
    Par mohe27 dans le forum Accès aux données
    Réponses: 20
    Dernier message: 17/08/2010, 02h28
  4. Question sur la dérivation à partir d'un modèle de classe
    Par Baubeau Cédric dans le forum Débuter
    Réponses: 3
    Dernier message: 11/12/2009, 18h02
  5. Réponses: 3
    Dernier message: 09/04/2009, 11h30

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