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

Linux Discussion :

unions anonymes sous Linux


Sujet :

Linux

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 86
    Points : 81
    Points
    81
    Par défaut unions anonymes sous Linux
    Bonjour,

    Je voudrais convertir une application Windows sous Linux et j'ai un problème avec les unions anonymes.
    J'ai besoin d'avoir une classe représantant des vecteurs pour une application 3D. Les composantes des ces vecteurs sont nomées x,yz,w ou s,t,r,q ou u,v,r,q selon le contexte. Mon code ce dessous compile bien sous Windows (Visual 2005) mais pas sous Linux

    Messages:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    /home/greg/Projets/MGX/MGX/MGX.h:96: error: declaration of ‘float MGXVECTOR4::<anonymous union>::<anonymous struct>::r’
    /home/greg/Projets/MGX/MGX/MGX.h:92: error: conflicts with previous declaration ‘float MGXVECTOR4::<anonymous union>::<anonymous struct>::r’
    /home/greg/Projets/MGX/MGX/MGX.h:96: error: declaration of ‘float MGXVECTOR4::<anonymous union>::<anonymous struct>::q’
    /home/greg/Projets/MGX/MGX/MGX.h:92: error: conflicts with previous declaration ‘float MGXVECTOR4::<anonymous union>::<anonymous struct>::q’
    :: === Build finished: 4 errors, 0 warnings ===
    Mon code:

    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
     
    class MGXVECTOR4{
    public:
    	union {
     
    		float Array[4];
    		struct {
    			float x,y,z,w;
    		};
    		struct
    		{
    			float u,v,r,q;
    		};
    		struct
    		{
    			float s,t,r,q;
    		};
    	};
    	explicit MGXVECTOR4()
    	{
    		x=0.0f;y=0.0f;z=0.0f;w=0.0f;
    	};
    	explicit MGXVECTOR4( float x , float y , float z, float w )
    	{
    		this->x = x; this->y = y; this->z = z;this->w = w;
    	}
    	inline operator float*()
    	{
    		return Array;
    	}
     
    	MGXVECTOR4 operator= (const MGXVECTOR4 &B)
    	{
    		if (this == &B) return B;
    		this->x = B.x;
    		this->y = B.y;
    		this->z = B.z;
    		this->w = B.w;
    		return B;
    	}
     
    	~MGXVECTOR4(){};
     
    	MGXVECTOR4 operator+ (const MGXVECTOR4 &B);
    	MGXVECTOR4 operator- (const MGXVECTOR4 &B);
    	float	  operator* (const MGXVECTOR4 &B);
    	MGXVECTOR4 operator* (float factor);
    	MGXVECTOR4 operator/ (float factor);
    };
    Est ce que cela veuy dire que je ne peux pas utiliser plusieurs fois le même nom de variable dans une union, même si ils font partis de structures différentes ?
    Y a t-il une solution ?
    Sachant que je n'utilise pas "float Array[4]", mais que j'en ai besoin pour être sûr de pouvoir convertir la classe en tableau de 4 float grâce à "inline operator float*()". Je pourrais renvoyer "&x", mais je suis pas sûr que les données seraient bien alignées en mémoire (x,y,z et w dans [0], [1], [2] et [3] ). On m'a dit sans certitude que ça force le compilateur à mettre x,y,z,w et ses synonymes (strq) dans le bon ordre et alignés.

    Merci.

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

    Informations professionnelles :
    Activité : aucun

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

    Je suis peut etre idiot, mais...

    Selon moi, que tes quatre valeurs s'appellent x,y,z et w ou s, t, r, q ou meme encore tic, tac, boulle et bil, ce n'est jamais qu'une pure question de convention

    Des lors, pourquoi ne pas "tout simplement" prévoir la place pour les quatre float en tant que membres privés (que ce soit sous la forme de float _m[4]ou sous une forme proche de float a,b,c,d) et, au pire, prévoir des "getter" pour les adapter aux convention

    D'autant plus qu'il y a, malgré tout, de fortes chances pour que s, x et u représentent en définitive effectivement la meme valeur

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 628
    Points : 30 692
    Points
    30 692
    Par défaut
    Pour préciser un peu mon intervention précédente:

    Les conventions de nommage que tu peux utiliser ont, en définitive, toujours trait à la meme abstraction (sans doute des valeurs Red Green Blue Transparancy/luminosity )

    Donc, selon moi, il est logique d'abstraire les valeurs et de décider une bonne fois pour toutes, par exemple, d'utiliser x à la place de u ou s, y à la place de v ou t, z à la place de r et w à la place de q en remplacant logiquement les variables dans les calculs...

    Selon moi, l'intéret d'une union n'est pas de permettre de fournir deux ou trois noms différents pour un meme type de variable, mais bel et bien de fournir plusieurs types d'interprétation pour une donnée, comme sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    union
    {
        char caract[4];/* si on considère qu'un entier c'est 32 bits, il faut quatre
                        * caracteres pour que la valeur entre en entier  ;) */
        int entier;
    };

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 366
    Points : 440
    Points
    440
    Par défaut
    Tu ne peux effectivement pas utiliser deux fois le meme nom de membre dans une union anonyme et c'est plutot logique. Prends ton code un peu modifier
    suivant:

    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
    class MGXVECTOR4{
    public:
    	union {
     
    		float Array[4];
    		struct {
    			float x,y,z,w;
    		};
    		struct
    		{
    			float u,v,r,q;
    		};
    		struct
    		{
    			float r,q,s,t;  // <-- CHANGEMENT d ordre
    		};

    quand tu parles alors de myvector.r ou myvector.q il y a une reelle ambiguite car suivant l union choisie (qui est ici implicite puisque anonnyme) l'adresse meme du membre r ou q peut etre differente.

    Par contre rien ne t empeche d ecrire plutot:


    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
     
     
    struct {
     
      union {
     
        float x;
     
        float u;
     
        float s;
      }
     
      union {
     
        float y;
     
        float v;
     
        float t;
      }
     
      ....
     
    }

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 86
    Points : 81
    Points
    81
    Par défaut
    Je vais donc supprimer la répétition du "r" et "q".

    koala01, ma classe devait permettre d'utiliser une même classe pour représenter des vecteurs ayant des nom d'attribut différents. s,t,r,q pour des textures, x,y,z,w pour des positions, ...
    Selon le même principe que dans les lib utilitaires de DirectX, des shaders HLSL, GLSL, CG, ...

    Meric.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 628
    Points : 30 692
    Points
    30 692
    Par défaut
    Mais tu n'as pas besoin d'avoir des noms d'attributs différents...

    Finalement, tu essaie de "coller" aux différentes conventions, et tu peux ne pas avoir tord... mais

    Une convention n'est jamais qu'une manière de nommer les choses qui t'est imposée de manière arbitraire

    Dés lors, que tu parles de position, de texture ou de quoi que ce soit d'autre, je te propose de prendre ta propre convention, qui puisse s'adapter à toutes les autres, vu qu'elles utilisent le meme type de valeurs:
    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
     
    class GXVECTOR4
    {
        public:
            GXVECTOR4(float first, float second, float third, float fourth);
            GXVECTOR4(float data[4]);
            float First(){return _data[0];}
            float Second(){return _data[1];}
            float Third(){return _data[2];}
            float Fourth(){return _data[3];}
            float *InArray(){return _data;}
            /* éventuellement */
            void SetFirst(float f){_data[0]=f;}
            void SetSecond(float s){_data[1]=s;}
            void SetThird(float t){_data[2]=t;}
            void SetFourth(float f){_data[3]=f;}
            /* et pourquoi pas */
            void FaitTrucDirectX(/*...*/){/*... */}
            void FaitMachinShader(/*...*/){/*...*/}
            void FaitBiduleOGL(/*...*/{/*...*/}
        private:
            float _data[4];
    };
    et de décider que
    • First() renvoye Array[0], x, u ou s selon le contexte
    • Second() renvoye Array[1], y, v ou r selon le contexte
    • Third() renvoye Array[2], z, r ou r selon le contexte
    • Fourth() renvoye Array[3], w q ou q selon le contexte
    • InArray() renvoye un pointeur sur le tableau si besoin

    De cette manière, tu obtient une classe qui peut tout faire, et qui est pleinement responsable de ce qu'elle représente

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 86
    Points : 81
    Points
    81
    Par défaut
    Je veux faire quelque chose qui ressemble le plus aux standards.
    Je pense qu'on a pas la même vision des choses (ce n'est pas une critique).

    J'ai absolument besoin de pouvoir faire par exemple:

    MGXVECTOR vec;
    vec.x = 3.0f;
    vec.s = 3.0f;

    avec x et s representant la même variable. Ceci n'est pas négociable

    Mais je me suis rendu compte que je peux me passer de u et v, pour cette classe. Donc mon problème est réglé.

    Merci pour ton aide.

  8. #8
    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
    Points : 15 920
    Points
    15 920
    Par défaut
    Pourquoi ne pas très simplement avoir plusieurs accesseurs plutôt que plusieurs variables membres ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    MGXVECTOR vec;
    vec.x() = 3.0f;
    vec.s() = 3.0f;
    Ca permet de combiner les avantages des deux points de vue.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 86
    Points : 81
    Points
    81
    Par défaut
    Pourquoi ne pas très simplement avoir plusieurs accesseurs plutôt que plusieurs variables membres ?
    Ce ne sera pas un poil plus lent ?

  10. #10
    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
    Points : 15 920
    Points
    15 920
    Par défaut
    Citation Envoyé par greg2
    Ce ne sera pas un poil plus lent ?
    Aucunement grâce à l'inlining.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 628
    Points : 30 692
    Points
    30 692
    Par défaut
    Il est peut etre bon de se rappeler que, le propre de l'informatique, c'est de rendre "concret" (grace au fait que l'application existe) quelque chose qui n'est que purement abstrait (une "vue de l'esprit").

    Du coup, tu peux envisager les choses sous deux angles différents:

    Soit, tu crées des classes pour chaque type de (groupe de) valeur que tu va gérer:
    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 Texture
    {
        /*...*/
    };
    class Array
    {
        /*...*/
    };
    class Shader
    {
       /*...*/
    }; 
    ...
    et tu considère que, finalement, le fait que chaque classe utilise le meme nombre de données d'un meme type n'est que pure coincidence, et ne présente, en définitive, aucun intéret:

    Quand tu veux travailler sur une texture, tu utilises la classe Texture, quand tu veux utiliser un shader, tu te tourne vers la classe Shader etc.

    L'autre optique est de réfléchir à
    Que puis-je faire pour me faciliter la tache
    Et là, tu te rend compte que, ben de fait, toutes les variables utilisent un meme nombre de données, que les données prises une à une sont exactement identiques et qu'en définitive, il n'y a que la convention qui change.

    Dans ce cas, tu estimes qu'il est clairement intéressant de séparer la représentation en mémoire des valeurs des différentes données de la manière dont tu y accede: cela s'appelle l'abstraction des données.

    Et là, tu peux envisager les deux solutions qui te sont données: soit, quarément, en fournissant des accesseurs/mutateurs purement arbitraire (GetFirst() et autres), soit en fournissant des accesseurs/mutateurs correspondant à chacune des conventions qui t'intéressent sous la forme indiquée par Laurent.

    Mais l'utilisation de l'union reste tres clairement la moins bonne de toutes les mauvaises solutions que tu puisse envisager

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

Discussions similaires

  1. [Série] Accès au port série sous linux
    Par ghost dans le forum Entrée/Sortie
    Réponses: 10
    Dernier message: 10/10/2007, 10h43
  2. Comment désinstaller MySQL sous linux
    Par nahmsath dans le forum Installation
    Réponses: 5
    Dernier message: 18/09/2007, 10h46
  3. installer jbuilder7 sous linux
    Par rtlinfo34 dans le forum JBuilder
    Réponses: 5
    Dernier message: 30/10/2002, 19h16
  4. Réponses: 2
    Dernier message: 25/10/2002, 22h19
  5. Je ne peux établir une connexion cliente sous Linux.
    Par Anonymous dans le forum CORBA
    Réponses: 5
    Dernier message: 16/04/2002, 15h57

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