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 :

Stocker une liste d'arguments de types différents sans "perdre" le typage


Sujet :

C++

  1. #1
    Membre averti
    Inscrit en
    Janvier 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Janvier 2006
    Messages : 47
    Par défaut Stocker une liste d'arguments de types différents sans "perdre" le typage
    Bonjour,

    Je voudrais stocker une liste d'arguments dans une std::list mais le problème c'est que je ne sais pas comment m'y prendre pour faire en sorte de pouvoir mettre des arguments de types différents, tout en étant capable ensuite, au moment où j'utiliserais la liste, de connaitre le type des différents éléments stockés.

    J'ai pensé aux templates mais le problème c'est que je ne peux avoir qu'une liste de données du même type. J'ai également pensé à un truc dans ce style :

    class A {}
    template<typename T> class B : public A { T m_Data; }

    et ensuite créer une liste de A* :
    std::list<A*> listA;

    ... ce qui pourrait convenir pour stocker les données dans ce style :
    B<int> * pb = new B<int>;
    listA.push_back(pb);

    .. mais le problème c'est qu'ensuite je ne pourrais plus récupérer les données correctement, à moins de connaitre explicitement leur type (ce qui n'est pas le cas évidemment, puisque ça change à chaque exécution).

    Si quelqu'un a une solution (qui m'éviterais de devoir stocker explicitement le type de chaque donnée et ensuite de faire des tests du genre if (nType == 1) alors c'est un int, 2 c'est un float, 3 c'est une string etc...), je suis preneur.

    Merci d'avance

  2. #2
    Membre expérimenté Avatar de Ksempac
    Inscrit en
    Février 2007
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 165
    Par défaut
    2nde solution (une classe mere dont herite toutes tes classes et une liste d'objets de type ta classe mere) + Dynamic_cast a la sortie

    Si le dynamic_cast renvoie autre chose que 0, tu viens de trouver le type de ce qui est sorti.
    Si le dynamic_cast renvoie 0, c'est pas le bon type, tu peux tenter le type d'apres.

    Cf la FAQ pour plus d'informations sur la syntaxe et l'utilisation de dynamic_cast

  3. #3
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par aiolia_aiolos
    .. mais le problème c'est qu'ensuite je ne pourrais plus récupérer les données correctement, à moins de connaitre explicitement leur type (ce qui n'est pas le cas évidemment, puisque ça change à chaque exécution).
    Qu'est-ce que tu veux faire avec des valeurs si tu n'en connais pas le type? Une fois qu'on sait ca, on peut commencer a proposer des solutions.

  4. #4
    Membre averti
    Inscrit en
    Janvier 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Janvier 2006
    Messages : 47
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Qu'est-ce que tu veux faire avec des valeurs si tu n'en connais pas le type? Une fois qu'on sait ca, on peut commencer a proposer des solutions.
    Je bosse sur une surcouche de LUA et je dois créer une fonction qui prend en argument la liste de paramètres et effectue, pour chaque valeur de la liste, des traitements spécifiques de lua (lua_pushstring, lua_pushnumber etc...) en fonction du type de la valeur.

  5. #5
    Membre averti
    Inscrit en
    Janvier 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Janvier 2006
    Messages : 47
    Par défaut
    Citation Envoyé par Ksempac
    2nde solution (une classe mere dont herite toutes tes classes et une liste d'objets de type ta classe mere) + Dynamic_cast a la sortie

    Si le dynamic_cast renvoie autre chose que 0, tu viens de trouver le type de ce qui est sorti.
    Si le dynamic_cast renvoie 0, c'est pas le bon type, tu peux tenter le type d'apres.

    Cf la FAQ pour plus d'informations sur la syntaxe et l'utilisation de dynamic_cast
    Oui, mais si j'ai bien compris l'idée, je serais quand même obligé de faire des tests pour chaque valeur du genre : si dynamic_cast<int> (valeur) == NULL alors ce n'est pas un int etc... Or, je voudrais éviter de faire ces tests. J'ai pensé qu'il y'avait sûrement moyen de faire ça d'un façon plus concise et plus optimisée en utilisant les templates mais je ne vois pas comment.

  6. #6
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Je ne vois pas en quoi une solution du genre:

    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 {
    public:
       virtual void act() = 0;
    };
     
    class AInt {
       ...
       void act() {lua_pushint(data); }
    };
     
    class AString {
       ...
       void act() {lua_pushstring(data); }
    };
    ne convient pas.

  7. #7
    Membre averti
    Inscrit en
    Janvier 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Janvier 2006
    Messages : 47
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Je ne vois pas en quoi une solution du genre:

    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 {
    public:
       virtual void act() = 0;
    };
     
    class AInt {
       ...
       void act() {lua_pushint(data); }
    };
     
    class AString {
       ...
       void act() {lua_pushstring(data); }
    };
    ne convient pas.
    Le problème c'est que ça m'oblige à instancier des classes différentes, or je dois stocker toutes les instances dans une seule liste, donc elle doivent être obligatoirement de même type (enfin si j'ai bien compris, en plus la classe A n'est pas parent des autres)

  8. #8
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par aiolia_aiolos
    Le problème c'est que ça m'oblige à instancier des classes différentes, or je dois stocker toutes les instances dans une seule liste, donc elle doivent être obligatoirement de même type (enfin si j'ai bien compris, en plus la classe A n'est pas parent des autres)
    A devait etre parent des autres, c'est un oubli que je vais corriger (sinon, a quoi servirait-elle?)

    Tu continues a stocker des pointeurs vers A.

  9. #9
    Membre averti
    Inscrit en
    Janvier 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Janvier 2006
    Messages : 47
    Par défaut
    Nom de dieu je suis bête, je crois avoir compris mais il faudrait que je teste

  10. #10
    Membre averti
    Inscrit en
    Janvier 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Janvier 2006
    Messages : 47
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    A devait etre parent des autres, c'est un oubli que je vais corriger (sinon, a quoi servirait-elle?)

    Tu continues a stocker des pointeurs vers A.
    Bon en fait non ça ne peut pas marcher car avec ta technique (polymorphisme classique) , les prototype de Act sont tous les mêmes. Or là, Act doit prendre un argument dont le type dépend justement de la classe en question. Par exemple le prototype du Act de AInt devra être Act ( int ).

    Je suis en train d'essayer avec les templates, voilà comment j'ai démarré :

    class Var{...};
    template<typename T> class TypedVar : public Var {void Push(T value); ...};

    class TypedVarInt : public TypedVar<int>
    {
    Push(int nValue)
    {
    lua_pushnumber(nValue);
    }
    }

    class TypedVarString : public TypedVar<string>
    {
    Push(string sValue)
    {
    lua_pushstring(sValue);
    }
    }


    ... et de même pour les autres classes. J'espère que ça va marcher, je vous tiens au courant

  11. #11
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    D'ou vient l'argument qui depend du type?

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Je ne vois pas pourquoi cela devrait influer sur le prorotype de Act().
    Selon moi, c'est le constructeur qui devrait dépendre du type...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre averti
    Inscrit en
    Janvier 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Janvier 2006
    Messages : 47
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    D'ou vient l'argument qui depend du type?

    En gros, voilà à quoi ça devrait ressembler :

    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
     
     
    class Var {...}
     
     
    template<typename T>
    class TypedVar : public Var
    {
        T value;
    public:
        T GetValue() {return value;}
    }
     
    // Fonction qui appelle une fonction LUA
    void CallLUAFunction (const char* szFunctionName,const list& ArgList, list&RetList);
    {
        // On récupère tousles arguments
        list<Var*>::iterator itArgList = ArgList.begin();
        while ( itArgList != ArgList.end() )
        {
            Var* pVar = *itArgList;
            // ensuite, on fonction du type de Var, je voudrais appeler une fonction lua :
            // si pVar encapsule un int, cad si pVar référence un TypedVar<int>, alors il faudrait que je puisse faire (mais je sais pas comment) :
            lua_pushint( pVar->GetValue() );
            // si pVar encapsule un string, cad si pVar référence un TypedVar<string>, je voudrais pouvoir faire : 
            lua_pushstring( pVar->GetValue() );
     
            etc...
     
     
        }
    }
     
     
    // programme client 
    list<Var*> ArgList;
    Var* p = new TypedVar <int>; 
    Arglist.push_back(p);
    p = new TypedVar <string>; 
    Arglist.push_back(p);
    CallLUAFunction ( "MaFonctionLUA", ArgList, RetList);

  14. #14
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Plutot que de faire un push(var->getValue) tu fais var->push().

  15. #15
    Membre averti
    Inscrit en
    Janvier 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Janvier 2006
    Messages : 47
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Plutot que de faire un push(var->getValue) tu fais var->push().
    Ah oui en effet, j'y avais pensé à un moment mais ensuite je me suis embrouillé. Je vais tester et je vais te dire si ça marche. Merci !

  16. #16
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Ton design à base de templates et de polymorphisme paraît assez lourd pour ce que tu veux faire.
    Pourquoi ne pas faire de CallLUAFunction une classe, définir les opérateurs adéquats, et utiliser la surcharge pour gérer les différents types ?

    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
    class LuaFunction
    {
    public :
     
        LUAFunction(const std::string& FuncName);
     
        // Pour passer des paramètres
        LuaFunction& operator <<(int Arg);
        LuaFunction& operator <<(float Arg);
        LuaFunction& operator <<(const std::string& Arg);
     
        // Pour appeler la fonction
        bool operator ()();
     
        // Pour récupérer les valeurs de retour
        LuaFunction& operator >>(int& Ret);
        LuaFunction& operator >>(float& Ret);
        LuaFunction& operator >>(std::string& Ret);
    };
     
    LUAFunction F("DoSomething");
    F << 5 << "bop";
    if (F())
    {
        int Ret;
        F >> Ret;
    }
    Ca s'éloigne un peu de ton design, mais si jamais ça peut donner des idées...
    Tu peux aussi remplacer << et >> par (), si tu veux des trucs moins verbeux.

    Au fait, c'est pour le fun ? Parce que des wrappers Lua C++, il en existe de très bons (luaBind est sans doute le meilleur).

  17. #17
    Membre averti
    Inscrit en
    Janvier 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Janvier 2006
    Messages : 47
    Par défaut
    Ok, ça maaaaarche !!!

    Bon merci pour tout et à plus !

  18. #18
    Membre averti
    Inscrit en
    Janvier 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Janvier 2006
    Messages : 47
    Par défaut
    Citation Envoyé par Laurent Gomila
    Ton design à base de templates et de polymorphisme paraît assez lourd pour ce que tu veux faire.
    Pourquoi ne pas faire de CallLUAFunction une classe, définir les opérateurs adéquats, et utiliser la surcharge pour gérer les différents types ?

    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
    class LuaFunction
    {
    public :
     
        LUAFunction(const std::string& FuncName);
     
        // Pour passer des paramètres
        LuaFunction& operator <<(int Arg);
        LuaFunction& operator <<(float Arg);
        LuaFunction& operator <<(const std::string& Arg);
     
        // Pour appeler la fonction
        bool operator ()();
     
        // Pour récupérer les valeurs de retour
        LuaFunction& operator >>(int& Ret);
        LuaFunction& operator >>(float& Ret);
        LuaFunction& operator >>(std::string& Ret);
    };
     
    LUAFunction F("DoSomething");
    F << 5 << "bop";
    if (F())
    {
        int Ret;
        F >> Ret;
    }
    Ca s'éloigne un peu de ton design, mais si jamais ça peut donner des idées...
    Tu peux aussi remplacer << et >> par (), si tu veux des trucs moins verbeux.

    Au fait, c'est pour le fun ? Parce que des wrappers Lua C++, il en existe de très bons (luaBind est sans doute le meilleur).
    Oups désolé je n'avais pas vu ton message. Ben en fait ce n'est pas pour le fun c'est pour le boulot, mais à vrai dire je fais ce que le chef de projet m'a demandé (en gros reprendre le wrapper de leur moteur et le refaire plus proprement, parce qu'avant ils y allait à coup de test du genre if type=truc then machin )

    Sinon pour ton idée de classe, je vais essayer voir ce que ça donne, j'avoue que étant au taf je n'ai pas trop eu le temps de me pencher dessus parce que j'ai pris un peu de retard mais ce soir quand y'aura moins de pression je regarderais (je sais pour avoir lu tes tutoriaux que tu es LE spécialiste des templates et par conséquent je m'attendais à te voir intervenir )

    En tout cas merci à vous 2 !

  19. #19
    Membre averti
    Inscrit en
    Janvier 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Janvier 2006
    Messages : 47
    Par défaut
    Sinon Loulou à propos de ce que tu propose, je crois que ça ne va pas plaire au lead parce qu'il ne veut pas qu'on réimplémente un nouveau prototype pour chaque type, il veut à tout prix que j'utilise les template (c'est son obsession)

  20. #20
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    je sais pour avoir lu tes tutoriaux que tu es LE spécialiste des templates et par conséquent je m'attendais à te voir intervenir
    Il y a ici plein de gens plus compétents que moi pour les templates et le C++ en général (dont Jean-Marc) mais merci pour le compliment

    Sinon Loulou à propos de ce que tu propose, je crois que ça ne va pas plaire au lead parce qu'il ne veut pas qu'on réimplémente un nouveau prototype pour chaque type, il veut à tout prix que j'utilise les template (c'est son obsession)
    Ok c'était juste une idée.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. type d'une colonne pour stocker une liste d'IDs
    Par zozor241 dans le forum Débuter
    Réponses: 1
    Dernier message: 07/04/2013, 19h18
  2. Réponses: 7
    Dernier message: 28/01/2011, 10h09
  3. Stocker une liste d'objets personnalisés dans les settings
    Par laville dans le forum Général Dotnet
    Réponses: 12
    Dernier message: 13/12/2007, 11h14
  4. Stocker une liste dans un fichier
    Par Knuckles dans le forum Général Python
    Réponses: 1
    Dernier message: 29/05/2006, 08h08

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