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 :

[Template] MetaProg : Connaître le type pointé d'un pointeur de membre


Sujet :

C++

Vue hybride

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

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut [Template] MetaProg : Connaître le type pointé d'un pointeur de membre
    Bonjour,

    Tout d'abord, j'ai peu d'espoir de trouver une solution. Voici mon problème :

    J'ai un composant qui a ses propres types, référencés par une énumération, que je dois utiliser. Puis des propriétés typé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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    enum COMPO_TYPE
    {
        INT = 0,
        FLT,
        STR,
        DBL,
        NONE
    };
     
    class IProperty
    {
    public:
       COMPO_TYPE GetCompoType() = 0;
    };
     
    template<class T>
    struct SCOMPO_HELPER
    {
       enum { VALUE = NONE };
    };
     
    template<>
    struct SCOMPO_HELPER<typename int>
    {
       enum { VALUE = INT };
    }
     
    template<>
    struct SCOMPO_HELPER<typename float>
    {
       enum { VALUE = FLT };
    }
     
    template<>
    struct SCOMPO_HELPER<typename double>
    {
       enum { VALUE = DBL };
    }
     
    template<>
    struct SCOMPO_HELPER<typename char*>
    {
       enum { VALUE = STR };
    }
     
    template<class T>
    class CProperty
    {
       // des méthodes
       COMPO_TYPE GetCompoType()
       {
           return SCOMPO_HELPER<T>::Value;
       }
    };
    Jusque là, tout vas bien. Mon composant utilise un tableau. Pour construire chaque colonne, il faut spécifier le type de cette colonne.
    Pour trouver le type de la colonne, je prends la première instance de mon type d'objet à représenter, puis je parcours ses propriétés et je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    IProperty* prop = RécupèreLaPropriété(monObjet, index);
    m_composant.AddColonne(prop->GetCompoType(), strLibellé);
    Sauf qu'admettons que je n'ai encore aucun objet instancier pour pouvoir récupérer le premier, et ensuite les types de ses propriétés pour construire les colonnes du tableau, je ne peux rien faire.

    Or, je connais le type de l'objet, et je peux récupérer des pointeurs de membres sur celui-ci, sous forme de "IProperty CUneClasse::*member".

    Est-ce que je peux bidouiller un truc pour récupérer le type réel de "CUneClasse::*member", sans aucune instance, et ensuite ci possible le paramètre template ?

    Au pire, je récupère le type réel, je l'instancie pour exécuter sa méthode GetCompoType() ?


    Ayant lu quelques trucs sur la méta programmation, j'me dis que peut-être il y a une solution à ça ?


    Merci beaucoup,

    Bonne soirée

  2. #2
    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
    Par défaut
    Salut,
    [préambule]Que CProperty n'hérite pas de IProperty est une erreur de copier/coller?[/préambule]
    Comment est définit la classe de monObjet? Si les propriétés sont un tableau dynamique, tu ne peux connaître le type qu'avec une instance. Sinon, je pense qu'il faut que tu nous montre un exemple de ce type de classe.
    A l'aveuglette, je dirais que peut-être tu peux trouver des pistes du côté de Boost.Preprocessor?

  3. #3
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Citation Envoyé par mister3957 Voir le message
    Est-ce que je peux bidouiller un truc pour récupérer le type réel de "CUneClasse::*member", sans aucune instance, et ensuite ci possible le paramètre template ?
    Une classe de traits ?

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut
    Oui oui, c'est une erreur de copier/coller, CProperty<T> hérite bien de IProperti*

    Un exemple de donnée metier :
    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
     
    // définitions de type en amont
    typedef CProperty<std::string> TStringProperty;
    // pareil avec long, int, uint, ulong etc..
     
    class CClient
    {
    public:
       const TULongProperty& GetIdent() const { return m_ulIdent; }
       const TStringProperty& GetName() const { return m_strName; }
     
    private:
       TULongProperty m_ulIdent;
       TStringProperty m_strName;
    };
     
    // Et j'ai une classe trait pour enregistrer les propriétés :
    template<class T>
    struct SPropertyRegistrer
    {
        static void Do();
    };
     
    template<> SPropertyRegistrer<CClient>::Do()
    {
        GesManager.RegisterProperty<CClient>(&CClient::m_ulIdent);
    }
    J'enregistre les propriétés auprès du gestionnaire, en les référençant par un pointeur de membre pour éviter de trop consommer la mémoire en les enregistrant à l'échelle des instances.
    Pour récupérer une propriété, je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        GesManager.GetDataProperty(monClient, "ID"); // renvoi un IProperty*
    L'enregistrement auprès du gestionnaire va caster le membre en "IProperty CClient::*" avant de le stocker dans une map avec l'identifiant passé comme clé.

    Dans un fichier XML, j'ai les correspondance entre les identifiants de properiétés, et les libellé des colonnes correspondantes. Donc je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    CClient* pData = GesManager.GetData<CClient>(0);
     
    // Parcours des correspondances pour arriver à ce genre de chose :
    IProperty* pProperty = GesManager.GetDataProperty(*pData, "ID");
    m_composant.AddColonne(pProperty->GetCompoType(), "Identifiant");
    Voilà, je suis donc obligé d'obtenir une instance quelque part pour récupérer sa propriété et en connaîtrele type correspondant du composant.

    Etant donné que je récupère un IProperty*, ou bien à la limite un IProperty CClient::*, je ne sais pas si une classe Trait pourrait convenir, puisque pour ça passera toujours dans MaClassTrait<IProperty> même si en fait c'est une StringProperty ou IntProperty n'est-ce pas ?

    Je vais regarde pour Boost.Preprocessor,


    Merci,

    A bientôt

  5. #5
    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
    Par défaut
    Je pense que Alp pensait à une classe trait sur CClient par sur IProperty.
    Ensuite, selon le temps que tu peux passer dessus (), Boost.MPL peut certainement aussi répondre à ton problème.

  6. #6
    screetch
    Invité(e)
    Par défaut
    dans le concept, c'est dommage que les propriétés ne soient pas de reelles propriétés mais les valeurs. Tu essayes de faire du RTTI mais le concept de RTTI est souvent :

    - il y a des classes (RTTIClass)
    - des proprietes (RTTIProperty)
    - (optionnel) des methodes (RTTIMethod) finalement assez proche des proprietes

    Pour chaque classe C++ qui a un RTTI, il existe une instance de RTTIClass, laquelle contient des RTTIProperty et des RTTIMethod

    une RTTIProperty ne contient aucune valeur, mais permet de retrouver la valeur quand on lui donne une instance, de sorte que meme sans instance, tu peux acceder aux proprietes (mais pas aux valeurs)

    soit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CClient
    {
      static RTTIClass s_metaclass;
      int m_memberInt;
    public:
      static const RTTIClass* metaclass;
      CClient();
    };
     
    RTTIClass CClient::s_metaclass("CClient", RTTIProperty<CClient,int>(offsetof(CClient::m_memberInt)); // TODO : si tu as de l'heritage, les metaclasses doivent avoir cette notion d'heritage
    RTTIClass* CClient::metaclass = &CClient::s_metaclass;
    c'est un exemple evidemment de syntaxe, ca pourrait etre different (ca devrait)
    ensuite, pour recuperer une proprieté, tu passes par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IProperty* p = CClient::metaclass->getProperty("name"); //pas d'instance
    et enfin, pour recuperer la valeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    p->as<int>()->getValue(instance);
    c'est comme ca que la plupart des langages avec introspection fonctionnent, et tu pourrais meme faire un pont entre C# (mono) et ton RTTI ou encore python ou lua, car ils utilisent les memes concepts (tu aurais un mapping presque parfait entre leur RTTI et le tiens)

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut
    Cette histoire des RTTIClass et RTTIProperty au final contiennent une instance (static) de RTTIClass et des RTTIProperty qui la contiennent.

    Par ça, je comprends que les données méta sont dissociées des données métiers n'est-ce pas ?

    Ma classe client étant en fait de cette forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    template <class T>
    CIdentData<T>
    {
     
    };
     
    class CClient : public CIdentData<CClient>
    {
     
    };
    Donc si je ne veux pas rentrer dans du RTTI perso, je peux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template <class T>
    CIdentData<T>
    {
        static T s_OneData;
    };
     
    T CIdentData<T>::s_tTypeData();
     
    IProperty* p = GesManager.GetDataProperty(CIdentData<CClient>::s_OneData, "name");
    C'est le même principe (un peu plus brutalement) ou j'ai loupé quelque chose ?


    Merci

  8. #8
    screetch
    Invité(e)
    Par défaut
    C'est le meme principe, mais il faut alors que ton objet property ne soit qu'une couche supplémentaire qui permet de retrouver la valeur quand on lui donne l'instance, mais sinon c'est ca. mais c'est quoi le GesManager ?

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut
    Ok très bien, je vais faire un objet T static, constant pour éviter d'effectuer des opérations dessus qui ne soient pas constantes, puis on verra.

    Alors en fait le GesManager c'est un singleton qui possède une hiérarchie éparpillée regroupant les "GesIdentData<T>".

    Pour chaque type de donnée, j'aurai un gestionnaire permettant de les charger, les stocker, appliquer les modifs et les supprimer. Un gestionnaire référence également les propriétés des données (map<string, IProperty T::*), les propriétés identifiantes (vector<string>), puis les relations entre les entités (1-0/1, 1-n) en enregistrant.

    Et donc le GesManager a été fait pour éviter de tomber dans la singletonite, disons que c'est le point d'entré vers les gestionnaires de donné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
    17
    18
    19
    20
     
    template <class T>
    struct SGesHolder
    {
        CGesIdentData<T>
    };
     
    typedef TTYPELIST_3(CCustomer, CVehicle, CProduct) TGesList;
     
    class CGesManager : public CSingleton<CGesManager>, public CScatteredHierarchy<TGesList, SGesHolder>
    {
        template<class T> void Load()
        {
             SGesHolder<T>::Ges/Load();
        }
     
        // Etc pour les autres méthodes des ges
    };
     
    #define GesManager CGesManager::Instance()
    Et ensuite à l'utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    GesManager.Load<CCustomer>();
    Et c'est encore plus pratique lorsqu'une fonction utilise le type du template :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    CCustomer monClient;
    CVehicle monVehicule;
     
    GesManager.Delete(monClient);
    GesManager.Delete(monVehicule);

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. Connaître le type du template
    Par Flo. dans le forum Langage
    Réponses: 13
    Dernier message: 20/02/2008, 04h26
  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