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 :

Connaître le type du template


Sujet :

Langage C++

  1. #1
    Membre chevronné Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Par défaut Connaître le type du template
    Bonjour, je voudrais travailler avec une classe templatée ClassB<T> qui se construirait à partir de d'une autre classe templatée ClassA<T>. Du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ClassA<T> maClassA;
    ClassB<T> maClassB(maClassA);
    Par contre, si au moment d'instancier un objet de ClassB<T> je ne connais pas T, comment faire ?

    ClassA<T> pourrait créer un ClassB<T> mais on se trouverait dans des includes croisée.

    J'ai également vu dans certains posts que Boost possèderait des outils pour ce faire. Mais je me dis que la stl doit posséder ses propres solutions non ?

    Merci

    Flo.

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    865
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 865
    Par défaut
    Pourrais-tu expliquer un peu plus ton problème ? Est-ce que tu cherches à faire quelque chose comme ceci.
    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
     
    template <typename T>
    class A {
    public:
      A (const T & i) : _i (i) {}
    private:
      T _i;
    };
     
    template <typename T>
    class B {
    public:
      B (const A<T> & a) : _a (a) {}
    private:
      A<T> _a;
    };
     
    int main () {
      A <int> a (1);
      B <int> b (a);
      return 0;
    }
    Par contre, si au moment d'instancier un objet de ClassB<T> je ne connais pas T, comment faire ?
    C'est là que je ne suis pas... Ton type T doit forcément être connu à la compilation. Si tu ne peux pas encore déterminer le type T à l'instanciation d'un objet de la ClassB, il faut que la fonction ou la classe qui fait cette instanciation soit aussi un template...

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Bonjour, je voudrais travailler avec une classe templatée ClassB<T> qui se construirait à partir de d'une autre classe templatée ClassA<T>.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T>
    struct ClassA
    {
        typedef ClassB<T> make_ClassB;
    };

  4. #4
    Membre chevronné Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Par défaut
    En fait c'est dans un contexte de mécanisme de polymorphisme. Et c'est également en managé .NET ...

    Une classe A dont vont hériter toutes les objets de classe B templatées :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ref ClassA
    {
    public: ClassA()
    {
    }
    };
    Une classe B templatée qui hérite de classe A :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <class T> ref ClassB : ClassA
    {
    public: ClassB()
    {
    }
    };
    Une classe C templatée qui se construit à partir d'une classe B.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <class T> ref ClassC
    {
    public: ClassC(ClassB<T> ^ classB)
    {
    }
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main()
    {
    // on crée 2 objets de classe B de type T différents
    ClassB<int> ^ classB1 = gcnew ClassB<int>;
    ClassB<double> ^ classB2 = gcnew ClassB<double>;
     
    // je les mets dans une liste de type de la classe A
    List<ClassA ^> ^ desClassB = gcnew List<ClassA ^>;
    desClassB->Add(classB1);
    desClassB->Add(classB2);
    }
    Ensuite je veut créér un un objet de ClassC à partir de chaque objet de ClassB contenu dans la liste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    for(int index = 0; index < (int)desClassB.size(); index++)
    {
    if(dynamic_cast<ClassB<int>>(desClassB[index]))
         ClassC<int> ^ classC = gcnew ClassC<int>(dynamic_cast<ClassB<int>>(desClassB[index]));
     
    else if(dynamic_cast<ClassB<double>>(desClassB[index]))
    ClassC<double> ^ classC = gcnew ClassC<double> (dynamic_cast<ClassB<double>>(desClassB[index])); 
    }
    N'y a-t-il pas moyen de se passer des comparaisons précédente et d'utiliser une méthode plus ... générique, style (c'est n'importe quoi bien sur) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    for(int index = 0; index < (int)desClassB.size(); index++)
    {
    ClassC<typeid(desClassB[index])> ^ classC = 
           gcnew ClassC<typeid(desClassB[index])>(dynamic_cast<ClassB<typeid(desClassB[index])>>(desClassB[index]);
    }
    J'espère que c'est plus clair. Et désolé quant au c++.NET mais je voulais avoir en c++ non managé car la même problématique se poserait (en tous cas pour moi) en c++ standart.

    Flo.

  5. #5
    screetch
    Invité(e)
    Par défaut
    si ClassC est une classe fille de ClassParentC, alors tu peux demander a ClassA de creer le ClassC correspondant, en le manipulant ensuite sous forme de ClassParantC

    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
    15
    ClassA
    {
      virtual ClassParentC* makeC() = 0;
    };
     
    ClassB<T>
    {
      virtual ClassC<T>* makeC() { return new ClassC<T>; }
    };
     
    ...
    for(int index = 0; index < (int)desClassB.size(); index++)
    {
         ClassParentC^ classC = desClassB[index]->makeC();
    }
    'est un mix C++ non managé/managé mais tu peux t'y retrouver.

    Plus précisément : tu stockes dans un vecteur des objets generiques, tu ne pourras plus jamais manipuler les types précis sans recourir au dynamic_cast. a partir du moment ou tu as perdu le type exact, tu vas devoir travailler avec un type restreint. au mieux, tu peux restreindre les autres types pour s'accomoder (c'est a dire, creer une classe ClassParentC qui va regrouper les differentes fonctionnalités communes a tous les ClassC).

    Si cela ne convient pas, tu vas devoir soit demander dynamiquement le type, soit _ne pas perdre le type precis_ en stockant tes valeurs dans differents tableaux au lieu d'un seul.

  6. #6
    Membre chevronné Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Par défaut
    Je te remercie mais la solution ne me convainc pas.

    Je préfère tester mes types un par un.

    Merci quand même.

    Flo.

  7. #7
    screetch
    Invité(e)
    Par défaut
    c'est souvent signe d'un defaut d'implementation, voir le post suivant :

    http://www.developpez.net/forums/sho...d.php?t=490821

  8. #8
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Ce qui est toujours une faute de conception.
    Fais plutôt un visiteur.

  9. #9
    Membre chevronné Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Par défaut
    Ouais celle-là elle est facile !!! ... Le coup de la faute de conception ...

    Sur un post d'un forum GeekZone, le sujet a déjà été abordé

    http://www.geekzone.fr/ipb/index.php?showtopic=35980

    Et boost semble y avoir apporter une réponse.

    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
    typedef if_c<true, bool, int>::type TypeB;
    typedef if_c<false, bool, int>::type TypeC;
     
     
    class Factory
    {
    private:
        Factory() {}
     
     
    private:
        template <class T, class _Param> static A* Instantiate(_Param p)
        {
            return new T(p);
        }
     
    public:
        template <class _Param> static A* CreateNewObject(_Param p)
        {
            return Instantiate<eval_if_c<is_same<_Param, TypeB>::value, identity<B>, identity<C> >::type, _Param>(p);
        }
     
    };
    Mais je souhaiterais savoir si il n'existe pas de solutions plus standarts.

    Faute de conception, qu'est-ce-qui faut pas dire pour apparaître dans un post.

    Flo.

  10. #10
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Vérifier le type dynamique d'un objet parmi toutes les combinaisons est toujours une erreur de conception.
    Mais bon, tu t'exprimes très mal, et l'extension avec la boule de cristal donne de mauvais résultats sur toi, du coup je suis tombé deux fois de suite à côté de ce dont tu parlais.
    Je n'ai donc toujours aucune idée de ce que tu essaies de faire.

    Quoiqu'il en soit, le code de eval_if fait deux lignes tu sais...

  11. #11
    Membre chevronné Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Quoiqu'il en soit, le code de eval_if fait deux lignes tu sais...
    Et bien tu me l'aurais écris le code de eval_if, au lieu de me débiter tes niaiseries, ça m'aurait permis d'avancer ...

    Quant aux erreurs de conception ... on travaille pas toujours sur des projets ou du jour au lendemain, on peut dire ...

    "Tiens je vais refaire l'uml de mon projet vieux de 5 ans"

    ... donc si je peux m'éviter de retaper les 10zaines de fichiers du projet surlequel je travaille, mon boss appréciera (... du style "Hé boss, ton code surlequel tu bosses depuis 5 ans il es nul ... tu permets que je le refasse pour la fin du mois").

    Donc avant de tout mettre sur l'erreur de conception, que je ne peux pas résoudre dans l'immédiat, on répond à la question si on sait, mais on vient pas ramener sa fraise surtout si c'est pour cloturer par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Quoiqu'il en soit, le code de eval_if fait deux lignes tu sais...
    et ne pas le donner

    Flo.

  12. #12
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 540
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 540
    Par défaut
    Les types doivent être connus à la compilation comme le dit Aoyou c'est pour ça qu'il faut faire des déclarations à rallonge avec les patrons de classes.

    Le compilo lui quand il voit par exemple int a, il réserve 4 octets ( par exemple selon l'OS) à une adresse du programme et une fois compilé le programme ne sait rien des int, char etc..
    Le programmme à l'exécution ne connait que les décalages mémoires à effectuer.
    C'est à la compilation que ces décalages sont écrits.

    En .NET c'est différent, ici c'est le forum C++ non managed.

    Tu peux utiliser par exemple les _variant de COM cela serait une solution mais c'est une tech Microsoft
    Donc soit tu fais tes classes en .NET et tu les mixes avec du code C++ natif sinon je ne vois pas de solution..

  13. #13
    screetch
    Invité(e)
    Par défaut
    dis donc la on est pas payé pour t'aider ici, alors que toi tu as l'air d'etre payé pour le faire. donc si nos reponses ne sont pas satisfaisantes, je pense que tu peux tenter _POLIMENT_ de continuer tout seul. j'insiste sur le poliment.

  14. #14
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Par défaut
    Citation Envoyé par Flo. Voir le message
    [...]
    Faute de conception, qu'est-ce-qui faut pas dire pour apparaître dans un post.
    Peut-être réflechir avant d'écrire du code -_-

    Et bien tu me l'aurais écris le code de eval_if, au lieu de me débiter tes niaiseries, ça m'aurait permis d'avancer .
    T'es drôlement poli dis moi. À mon avis, tu vas devoir te débrouiller tout seul maintenant.

Discussions similaires

  1. Connaître le type d'un template
    Par jfouche dans le forum Langage
    Réponses: 3
    Dernier message: 04/08/2011, 15h09
  2. Réponses: 9
    Dernier message: 27/11/2008, 18h38
  3. Connaître le type d'un champs d'une table Mysql
    Par xoran dans le forum Langage SQL
    Réponses: 1
    Dernier message: 20/07/2005, 09h29
  4. [POO] Comment connaître le type d'un objet
    Par zizou39 dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 01/03/2005, 09h46
  5. [Access] Connaître le type de donnée
    Par Ric1983 dans le forum Bases de données
    Réponses: 4
    Dernier message: 15/02/2005, 19h09

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