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++

  1. #1
    Membre régulier
    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
    Points : 119
    Points
    119
    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 éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 562
    Points : 7 628
    Points
    7 628
    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 régulier
    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
    Points : 119
    Points
    119
    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 régulier
    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
    Points : 119
    Points
    119
    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
    739
    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 : 739
    Points : 3 627
    Points
    3 627
    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 régulier
    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
    Points : 119
    Points
    119
    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!

  7. #7
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    Si la spécialisation n'était qu'un héritage caché il y aurait plus de problèmes qu'autres choses et on a déjà l'héritage donc à quoi bon avoir un autre système complexe pour la même chose ?
    La spécialisation est toujours complète, d'où le terme.
    Comme d'habitude ajouter une indirection, ici une classe de base, permettrait de contourner la chose.

    un ensemble de types, fonctionnant (à peu près) de la même manière, mais qui n'ont rien d'autre en commun
    Et pourquoi pas de fonctions libres au lieu de tout mettre dans une classe quelconque ??
    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.

  8. #8
    Membre régulier
    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
    Points : 119
    Points
    119
    Par défaut
    Bonjour,

    Attention, il ne s'agît pas du tout de la même chose :
    l'héritage (comme je le connais en tous cas) résout principalement les liens à l'exécution. Un objet qui hérite d'un autre est du même type à la base. Un oiseau est un volatile. Il spécialise simplement la manière de voler. Héritage. De plus, je peux dire volatile->vole, sans me préoccuper du fait que c'est une mésange ou un avion...
    un vecteur d'entiers fait la même chose qu'un vecteur d'oiseaux, mais ce sont deux objets assez fondamentalement différents et il n'est évidemment pas question que l'un hérite de l'autre. L'ensemble des opérations qui ne sont pas dépendantes du type d'objets contenus (ajout / suppression ...) sont rassemblées et codées dans un modèle (template). Et presque tous les liens du modèle sont résolus à la compilation. Par contre je ne peux pas dire à un vecteur dont le contenu n'est pas défini d'effectuer des opérations, car tant que je n'aurais pas précisé la nature de son contenu, aucun vecteur ne pourra exister (instanciation).
    Si alors je parle d'héritage de modèles, mon idée n'est pas de rajouter une couche d'édition de liens automatique, mais bien de dire par exemple, pour les oiseaux, mon vecteur se comporte d'une manière légèrement différente, en ajoutant des coussins sur les balançoires dans les cages par exemple, ce que ne ferait pas le vecteur d'entiers, tout en ne m'obligeant à (ré)écrire que la partie du modèle effectivement impactée par ce changement.
    en gros :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     #include <vector>
    using namesoace std;
    template<> class vector<oiseau> is_same // <-- un terme pour dire qu'on s'inspire du modèle de base
    {
        // mécanismes ajoutés, modifiés ou éventuellement supprimés
        vector<oiseau> insert( oiseau & ) // <-- interface de insert modifiée
       ...
    };
     
    ...
    {
    ...
    vector<oiseau> V; V.insert(oiseau) <-- utilise la méthode de vector<oiseau> redéfinie dans ma spécialisation
    vector<uint> V; V.insert(3) <-- utilise la méthode insert de vector<uint> qui n'est pas la même
    Bien entendu l'exemple est complètement farfelu. J'espère simplement qu'il permet d'expliquer correctement ce que je veux dire.

    Et pourquoi pas de fonctions libres au lieu de tout mettre dans une classe quelconque ??
    Pourquoi pas en effet...
    Actuellement j'ai un fichier où près de 1000 fonctions libres sont écrites (il y a 20 ans quand les modèles n'existaient pas encore), la plupart faisant la même chose, juste avec un petit aspect différent (un type d'argument etc...). Leur regroupement dans une hiérarchie de classes ne permettait pas d'en réduire le nombre (pas suffisamment liées entre elles).
    Ces fonctions ont déjà quelque peu été factorisées, et définies en utilisant des macros, ce qui fait que la plupart ne prennent pas plus de deux lignes. C'est très bien, et le programme a fonctionné comme cela.
    Cependant, maintenant, il faut que j'y remette le nez, après fort longtemps, et malgré les commentaires et autres informations, j'ai un peu du mal à m'en sortir.
    J'ai donc décidé de faire un vrai travail de factorisation, qui devrait me permettre de réduire ce nombre à une centaine, et d'avoir un code lisible et compréhensible, au moins par moi-même... Et la réflexion m'a bien sur amené plus loin que la modélisation de fonctions, ce qui a amené ma question.

    Pour ma part mon problème est résolu. Je laisserai le sujet ouvert un temps au cas où j'aurais dit des conneries, et que quelqu'un voudrait me le faire savoir
    En tout état de cause, merci pour vos réponses!

    A bientôt!

  9. #9
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Teaniel Voir le message
    Par contre je ne peux pas dire à un vecteur dont le contenu n'est pas défini d'effectuer des opérations
    Et pourtant c'est exactement ce que fait std::vector et plus largement tout le contenu de std::algorithm...
    C'est même le principe-même du template et de la méta-prog, de faire quelque chose quelque soit le contenu auquel on l'applique.

    Citation Envoyé par Teaniel Voir le message
    mon vecteur se comporte d'une manière légèrement différente, en ajoutant des coussins sur les balançoires dans les cages par exemple
    Mais ceci n'a rien à voir avec une spécialisation de vecteur. C'est à peine un comportement différent. Et ça se résoud parfaitement bien avec du template et de la méta-prog, voire avec de la simple surcharge de fonction en fait.
    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.

  10. #10
    Membre régulier
    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
    Points : 119
    Points
    119
    Par défaut
    Excuse moi, je me suis mal exprimé.
    Je vais essayer de le dire autrement : voici le genre de problème qui m'était posé, et que j'avais à résoudre (j'en ai ajouté un peu, il s'agissait d'un truc beaucoup plus simple).
    modèle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     template <class X> class A {
    ... // 500 lignes Base
    public:
    X unefonction(X &x);
    X *une_variable;
    };
    spécialisation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Y;
    template<> class A<Y> {
    ... // 500 lignes Base recopiées
    private:
    Y *unefonction(Y x);
    Y une_variable;
    };
    Ma question était : Y aurait-il un moyen simple de ne pas avoir à réécrire les 500 lignes Base. Pour moi c'est cela que signifie spécialisation. Pas on jette tout et on recommence.
    La raison en est simplement la maintenance (si des choses changent dans les 500 lignes Base, je suis obligé de les reporter).
    Dans mon cas, il s'agissait simplement d'ajouter une fonction dans la spécialisation. Je l'ai résolu en l'ajoutant au modèle, comme ça c'est dispo pour toutes les classe, mais ça introduit un comportement non défini si elle est utilisée autrement que pour le paramètre du modèle prévu. Et c'est pour cela que j'ai parlé d'héritage de modèle.
    Petite précision : l'exemple ci-dessus ne représente qu'un exemple théorique, et les modifications introduites sont purement imaginaires, et il est possible qu'individuellement une solution existe. C'est uniquement le principe que je voulais montrer.

    A bientôt!

  11. #11
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    Et je te renvoie au message précédent : tout problème peut se fixer en ajoutant une indirection et tu n'as pas à ajouter une fonction membre mais peux parfaitement ajouter une fonction libre.
    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.

  12. #12
    Membre régulier
    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
    Points : 119
    Points
    119
    Par défaut
    Bonjour,

    Ok. Va pour la fonction :
    Spécialisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Y *unefonction(A<Y> *ths, Y x);
    Ça ressemble à une spécialisation de unefonction pour le type Y dans A, sauf qu'on change la signature.
    Petit inconvénient : il faut appeler explicitement la fonction. Elle ne sera jamais appelée si le type Y est donné en paramètre d'un objet générique qui provoquerait l'appel à unefonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template <class T>
    uneAutreFonction<T>(...){
        A<T> var;
       ...
       var.unefonction<T>(...); // N'utilisera jamais le prototype fourni ci-avant, si appelé dans la fonction ci-après.
    }
     
    int test() {
       uneAutreFonction<Y>(...);
    }
    Je suis bien d'accord que rajouter une fonction libre pourrait permettre de résoudre certains cas particuliers.

    Je comprends bien, au final, que C++ ne fournit pas de solution simple à ce problème. Chaque cas de modification est particulier et doit donc trouver sa solution particulière.
    En lisant un peu, cette semaine, je suis tombé sur une notion que je ne connaissais pas encore, et qui, semble-t-il consiste à créer des classes amies de la classe générique comportant une partie de son interface. On appelle cela classe trait, c'est souvent cité, mais peu ou pas expliqué. Je vais creuser un peu de ce côté là.

    A bientôt

  13. #13
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    Le C++ propose sûrement plusieurs solutions que tu refuses ou n'es pas capable de voir.
    Et ce n'est pas avec un problème partiel et des conditions qui changent à chaque réponse qu'on va en trouver une.
    Il n'y a quasi aucune différence entre une simple fonction membre et libre. C'est juste une syntaxe (d'appel et d'écriture) différente. Et si en plus tu parles maintenant d'amitié, il y en a encore moins.
    Petit inconvénient : il faut appeler explicitement la fonction.
    Et comment espères-tu appeler ta nouvelle fonction si ce n'est explicitement ?! En l'ajoutant dans la classe son appel deviendrait magique et implicite ?
    X unefonction(X &x);
    X *une_variable;
    ..
    Y *unefonction(Y x);
    Y une_variable;
    Ta spécialisation change la signature d'une fonction et le type d'un membre (et sûrement un tas d'autres de trucs que tu as omis). On n'est déjà plus dans l'ajout de fonctionnalité sur un type donné.
    Mais ici encore une simple indirection supplémentaire peut gérer ce cas. Un trait peut être cette indirection.
    Mais ça complexifie l'utilisation.
    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.

  14. #14
    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 611
    Points
    30 611
    Par défaut
    Citation Envoyé par Teaniel Voir le message
    Excuse moi, je me suis mal exprimé.
    Je vais essayer de le dire autrement : voici le genre de problème qui m'était posé, et que j'avais à résoudre (j'en ai ajouté un peu, il s'agissait d'un truc beaucoup plus simple).
    modèle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     template <class X> class A {
    ... // 500 lignes Base
    public:
    X unefonction(X &x);
    X *une_variable;
    };
    spécialisation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Y;
    template<> class A<Y> {
    ... // 500 lignes Base recopiées
    private:
    Y *unefonction(Y x);
    Y une_variable;
    };
    Ma question était : Y aurait-il un moyen simple de ne pas avoir à réécrire les 500 lignes Base. Pour moi c'est cela que signifie spécialisation. Pas on jette tout et on recommence.
    La raison en est simplement la maintenance (si des choses changent dans les 500 lignes Base, je suis obligé de les reporter).
    Dans mon cas, il s'agissait simplement d'ajouter une fonction dans la spécialisation. Je l'ai résolu en l'ajoutant au modèle, comme ça c'est dispo pour toutes les classe, mais ça introduit un comportement non défini si elle est utilisée autrement que pour le paramètre du modèle prévu. Et c'est pour cela que j'ai parlé d'héritage de modèle.
    Petite précision : l'exemple ci-dessus ne représente qu'un exemple théorique, et les modifications introduites sont purement imaginaires, et il est possible qu'individuellement une solution existe. C'est uniquement le principe que je voulais montrer.

    A bientôt!
    Salut,
    Oui, bien sur qu'il y a un moyen simple : tu crées une classe modèle pour tout le tronc commun, que tu utilise au travers du CRTP:
    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>
    class Base{
    protected:
        // only functions, using private members
    private:
       // maybe some private, strictly internal functions
       // private members
    };
    template <typename X>
    class A :public Base<X>{
    public:
       X foo();
       X* myVar;
    };
    template<>
    class A<Y> : public Base<Y>{
    public:
        Y bar();
        Y* ptr;
    };
    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

  15. #15
    Membre régulier
    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
    Points : 119
    Points
    119
    Par défaut
    Bonjour,

    Merci, koala01,
    Je n'y avais en effet pas pensé sous cet angle. C'est effectivement simple.
    Désolé pour mon insistance, mais il m'arrive dès fois de bloquer sur une question et de ne plus voir au delà du bout de mon nez ensuite.
    Merci à tous pour vos réponses et le temps que vous m'avez consacré.

    A bientôt!
    Marc

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 22/04/2013, 13h07
  2. Problème modèle et classe lier
    Par obarator dans le forum Visual Studio
    Réponses: 1
    Dernier message: 05/07/2011, 17h07
  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, 03h28
  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, 19h02
  5. Réponses: 3
    Dernier message: 09/04/2009, 12h30

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