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 :

Recuperer le type d'une variable.


Sujet :

C++

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 10
    Points : 6
    Points
    6
    Par défaut Recuperer le type d'une variable.
    Bonjour,

    D'abord desole si mon probleme est un peu tordu ...

    Je souhaiterais recuperer le type T d'une variable, sachant que je ne connais que sa classe mere (donc je ne connais pas le "vrai" type de la variable, etant derive de cette classe mere). Cela me servirais pour incrementer un pointeur sur T.

    Concretement, je souhaiterais faire ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void
    example (std::vector<Vertex*> tableau)
    {
      void* ptr = ...;
     
      inc_pointer<void*, typeof (tableau[42])> (ptr); 
      // ptr pointe maintenant sur la case suivante
    }
    Pour l'instant, j'arrive a faire cela via cette classe templatee (is_pointer est un trait...), mais en donnant explicitement le type d'arrive (donc sans l'extraire d'une variable comme je souhaiterais):
    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
     
    template<typename SrcPtr, typename DstPtr>
    void 
    Pointer::inc_pointer (SrcPtr& ptr)
    {
      if (Pointer::is_pointer<SrcPtr>::result && Pointer::is_pointer<DstPtr>::result)
        ptr = &(((DstPtr) ptr)[1]);
      else
        // erreur
    }
     
    void
    exemple ()
    {
      void* ptr;
     
      Pointer::inc_pointer<void*, TypeDeDestination*> (ptr);
    }
    Quelques precisions:
    • etant sous visual studio 2008, je n'ai pas acces a typeof (dailleurs qui n'est pas portable, non ?)

    • Je prefererais ne pas templater la fonction ou j'ai besoin d'incrementer mon pointeur, ca n'aurait pas de sens au niveau du role de la fonction

    • Eviter la solution crade du switch (code intrusif)

    • Je fais ca dans le cadre d'une fonction de rendu en DirectX9. C'est pour faire des memcpy de chaque vertex ecrit dans mon vertex buffer, donc il n'y a pas de problemes d'allocations ou des possibilites de violation d'acces...


    Merci d'avance pour l'aide que vous pourrez apporter !

    Altefquatre

  2. #2
    boli_971
    Invité(e)
    Par défaut
    Salut,
    En C++ il existe l'opérateur typeid(type) si sa peut t'aider.

    Exemple d'utilisation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main(int argc, char* argv[])
    {
    int var = 2009;
    if(typeid(var) == typeid(int))
       std::cout << "var est un int";
     
    }

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 10
    Points : 6
    Points
    6
    Par défaut
    Salut,

    J'avais lu 2 ou 3 trucs sur typeid, mais a la fin, ca reviens a faire un switch:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    switch (typeid (variable))
    {
    case typeid (MonType1):
      // traitement
      break;
    case typeid (MonType2):
      // traitement
      break;
    case typeid (MonType3):
      // traitement
      break;
    // etc...
    };
    Meme si ca marche, je souhaiterais faire du code plus generique et non intrusif comme je disais (je suis oblige de rajouter un cas si je cree un nouveau type). Dans l'ideal, ce serait quelque chose dans le style template / metaprogrammation.

    Merci quand meme de ta reponse.

  4. #4
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    La grande question étant: pourquoi tu as besoin d'un pointeur de type void ?
    Pourquoi ne pas utiliser un pointeur de type Vertex ? Ou mieux, un iterateur ?
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  5. #5
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    D'abord, j'aimerais savoir pourquoi tu veux incrémenter le pointeur, parce ce que ça risque de t'apporter des problème sans noms que de faire pointer ton pointeur sur l'adresse qui suit celle à laquelle se trouve ton objet

    De la même manière, décider d'utiliser comme paramètre template un pointeur sur void me parrait toujours suspect...

    Généralement, si tu veux pouvoir manipuler le type réel d'une classe template, il s'agit d'utiliser une classe template proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template <typename T>
    class MyClass
    {
        public:
            typedef T Type;
            typedef T& TypeRef;
            typedef T const & ConstTypeRef;
            typedef T* TypePtr;
            /*...*/
    };
    avec un exemple simple d'utilisation:
    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
    int main()
    {
     
        /* Nous pouvons accéder à une instance, à une référence
         * constante ou non et à un pointeur de n'importe quel type */
        MyClass<int>::Type var =0;
        MyClass<int>::TypeRef ref =var;
        MyClass<int>::TypePtr ptr = &var;
        MyClass<int>::ConstTypeRef constref = var;
        cout<< "avant incrementation par var "
            <<"var = "<<var<<" ref = "<<ref<<" constref = "
            <<constref<<" ptr ="<<ptr<<endl;
        var++;
        cout<<"apres incrementation par var "
            <<"var = "<<var<<" ref = "<<ref<<" constref = "
            <<constref<<" ptr ="<<ptr<<endl;
        ref++;
        cout<<"apres incrementation par ref "
            <<"var = "<<var<<" ref = "<<ref<<" constref = "
            <<constref<<" ptr ="<<ptr<<endl;
        /* constref++; serait refusé */
        return 0;
    }
    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

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 10
    Points : 6
    Points
    6
    Par défaut
    Desole si je suis assez locace, j'espere que ca repondra a vos questions...

    D'abord, j'aimerais savoir pourquoi tu veux incrémenter le pointeur
    En fait, comme je disais, c'est pour une fonction de rendu en directX, au niveau des vertex buffers.
    Si j'utilise un void*, c'est parce que la fonction Lock utilise un void** pour donner un pointeur (&vbuff) vers une zone memoire ou on peut inscrire nos vertice (vertex_size est un sizeof du type final de vertex, mais la j'utilise un switch juste pour pallier a mon probleme).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if (FAILED (hr = vb->Lock (0, vertice.size () * vertex_size,
                                        &vbuff, 
                                        D3DLOCK_DISCARD)))
        // erreur
    Ensuite, je fais des memcpy de chaque vertex sur la zone memoire en question:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    for (unsigned int i = 0; i < vertice.size (); ++i)
    {
      memcpy (vbuff, vertice[i], vertex_size);
     
      vbuff++; // on passe a la case suivante dans la zone memoire allouee par Lock
    }
    En principe, si Lock fait bien son boulot, il devrait retourner un pointeur vers une zone memoire valide, donc il ne devrait pas y avoir de probleme de memoire/addresses...

    De la même manière, décider d'utiliser comme paramètre template un pointeur sur void me parrait toujours suspect...
    Effectivement, j'aurais pu utiliser un Vertex*, mais ca reviendrait au meme sachant que je n'utilise pas les Vertex* mais des types derives uniquement.

    Apres ma hierarchie de classes pour les vertice est discutable, etant donne qu'il n'y a pas de fonction en virtual pour le polymorphisme (ex: pas de destructeur, car inutile ici)...
    En fait c'est plus des struct dans le sens C, c'est-a-dire que je n'ai uniquement que des champs. Si je souhaite eviter les methodes, c'est pour pouvoir faire des sizeof et des memcpy valides dans mon vertex buffer. (a chaque fois que je rajoute une methode, ca rajoute 4 octets a la classe et a ses derivees... 1 methode => 1 pointeur sur fonction ?).

    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
     
    class Vertex
    {
    public:
      Vertex (float x = 0, float y = 0, float z = 0);
     
      float x, y, z;
    };
     
    class Vertex3d : public Vertex
    {
    public:
      Vertex3d (float x = 0, float y = 0, float z = 0, 
                unsigned int r = 0, unsigned int g = 0, unsigned int b = 0);
     
      DWORD colour;
    };
     
    class Vertex2d : public Vertex
    {
    public:
      Vertex2d (float x = 0, float y = 0, float z = 0, 
                unsigned int r = 0, unsigned int g = 0, unsigned int b = 0);
     
      float rhw;
      DWORD colour;
    };
     
    class TexVertex2d : public Vertex2d
    {
    public:
      TexVertex2d (float x = 0, float y = 0, float z = 0,
                   float tu = 0, float tv = 0,
                   unsigned int a = 255, 
                   unsigned int r = 255, unsigned int g = 255, 
                   unsigned int b = 255);
     
      float tu;
      float tv;
    };
    Merci pour vos reponses

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 10
    Points : 6
    Points
    6
    Par défaut
    Bon et bien, si ca n'inspire pas grand monde, c'est que je me complique peut-etre trop la vie... Je crois que je vais rester sur un switch, vu que ca marche tres bien malgre l'aspect intrusif du code...

    Si ca peut interesser quelqu'un, voila grossierement comment je procede:
    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
    // get_size renvoit une taille en octets en fonction d'un argument
    size_t
    get_size (DWORD fvf_format)
    {
      switch (fvf_format)
      {
      case 1:
        return sizeof (Type1);
        break;
      case 2:
        return sizeof (Type2);
        break;
      // etc...
      }
    }
     
    void
    example (std::vector<Vertex*> vertice, DWORD fvf_format)
    {
      size_t vertex_size = get_size (fvf_format);
      char* vertex_buffer = NULL;
     
      // du code ...
      // initialisation de vertex_buffer sur une zone memoire valide
     
      // on copie chaque vertex
      for (int i = 0; i < vertice.size (); ++i)
      {
        memcpy (vertex_buffer, vertice[i], vsize);
     
        vertex_buffer += vsize;
      }
     
      // du code...
    }
    La raison du char* est qu'un char est sur 1 octet, et comme sizeof renvoit une taille en octets, si on a un type T de 5 octets par ex, pour aller a la case suivante de type T, c'est comme si on se deplacait de 5 cases de type char... (bon ok, c'est de la bidouille crado mais ca marche... :S)

    Merci de vous etre interesse a ce probleme.

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    A vrai dire, ce qui me chipote, c'est ta hiérarchie de classe Vertex...

    Typiquement, une classe de base est sensée fournir l'interface et éventuellement les données communes à l'ensemble des classes dérivées, or, ici, ta classe Vertex:
    1. fournit des données propres à la classe Vertex3D
    2. ne fournit aucune interface (aucune fonction membre qui puisse être utilisée par les classes dérivée)

    De plus, quitte à créer une classe dans laquelle tous les membres sont publics, autant créer une structure, pour laquelle l'accessibilité par défaut est publique

    Cela te donnerait quelque chose de proche de
    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
    /* il n'y a aucun rapport entre Vertex3D et Vertex2D, vu qu'il est
     * de toute manière hors de question de faire cohabiter les deux types
     * dans une même collection d'objets
     */
    struct Vertex3D
    {
        float x;
        float y;
        float z;
        DWORD colour;
    };
    struct Vertex2d 
    {
        float x;
        float y;
        float rhw;
        DWORD colour;
    };
    Enfin, il me semble utile de te rappeler deux conseils récurrents:
    1. préférer toujours les fonctions porpres au C++ à toute alternative issue du C
    2. Préférer la version des fonctions qui permettent de traiter les données par plages plutôt que celle traitant les données une à une

    En effet, le standard fournit la fonction copy, disponible dans l'espace de nom std, qui permet d'effectuer la copie d'une plage de valeurs se trouvant dans une collection (y compris dans un tableau C Style) dans une autre (qui peut également être un tableau C Style)

    Cela te permettrait d'écrire une fonction proche de
    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 T>
    void makeCopy(std::vector<T> const & vect)
    {
        T *tab;
        tab = new T[vect.size()];/* l'allocation de mémoire peut être effectué
                                  * par le biais de la fonction ad-hoc de directX;)
                                  */
        std::copy(vect.begin(),vect.end(),&tab[0]);
        /* ca, c'est juste pour te montrer que ca marche ;) 
         */
        for(size_t i = 0;i<vect.size();++i)
            cout<<tab[i].x<<" "<<tab[i].y<<" "<<tab[i].z<<endl;
        delete tab;
    }
    qui t'invite de devoir écrire la boucle et de devoir incrémenter un pointeur (même si la fonction copy fonctionne sans doute grace à une boucle en interne)
    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

  9. #9
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::copy(vect.begin(),vect.end(),&tab[0]);
    Plutôt :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::copy(vect.begin(),vect.end(),tab);
    non ?

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::copy(vect.begin(),vect.end(),&tab[0]);
    Plutôt :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::copy(vect.begin(),vect.end(),tab);
    non ?
    Oui, et non...

    Le fait est que, si tu veux copier au début du tableau "C style", tu peux effectivement utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::copy(vect.begin(),vect.end(),tab);
    mais que tu peux tout à fait décider de commencer la copie à l'indice x du tableau C style (par exemple lors d'une "concaténation" des données...

    Dans ce cas, ce sera d'office
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::copy(vect.begin(),vect.end(),&tab[x]);
    car ce sera quand même bien plus facile à lire qu'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::copy(vect.begin(),vect.end(),tab+(x* sizeof(LeType));
    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

  11. #11
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Tu voulais sûrement écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::copy(vect.begin(),vect.end(),tab+x);
    Et du coup, la lisibilité se discute plus...

    Je tique quand je vois du code type &tab[0], parce que j'ai toujours peur que ça soit un signe que la personne ne maîtrise pas ce qu'elle écrit (même si dans le cas présent, je suis assez convaincu du contraire ).

Discussions similaires

  1. determiner le type d'une variable
    Par Mokhtar BEN MESSAOUD dans le forum Langage
    Réponses: 1
    Dernier message: 14/03/2006, 17h11
  2. [VBA-E]Renvoyer le type d'une variable
    Par alexxx69 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 15/02/2006, 18h07
  3. Réponses: 2
    Dernier message: 19/01/2006, 21h59
  4. Connaitre le type d'une variable
    Par mic79 dans le forum Langage
    Réponses: 2
    Dernier message: 04/01/2006, 15h42
  5. Changer el type d'une variable sql sous postgre8/admin
    Par smag dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 24/08/2005, 12h31

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