Struktur mit Union initialisieren



  • Hi,

    ich habe gerade das Problem, dass ich es nicht hinbekomme, meine Mat4 Struktur zu initialisieren (ohne Konstruktor). Der Struktur habe ich eine Union spendiert, wenn ich die Union weglasse funktioniert alles wie gewohnt, also liegt es an der Union. In diesem Zusammenhang habe ich noch nie eine Union benutzt, also weiß ich nicht mehr weiter. Ich hoffe ihr könnt mir helfen.

    Mat4.h:

    #ifndef MAT4_H
    #define MAT4_H
    
    #include "Types.h"
    
    namespace sipgl
    {
    	struct SIPGL_API Mat4
    	{
    	public:
    		union
    		{
    			Float32 m[16];
    			Float32 m11, m21, m31, m41,
    				m21, m22, m23, m24,
    				m31, m32, m33, m34,
    				m41, m42, m43, m44;
    		}
    
    		static const Mat4 Identity;
    	};
    }
    
    #endif
    

    Mat4.cpp

    #include "Mat4.h"
    
    namespace sipgl
    {
    	const Mat4 Mat4::Identity = {1.0f, 0.0f, 0.0f, 0.0f,
    				0.0f, 1.0f, 0.0f, 0.0f,
    				0.0f, 0.0f, 1.0f, 0.0f,
    				0.0f, 0.0f, 0.0f, 1.0f };
    }
    

    Vielen Dank im Voraus!


  • Mod

    1. Warum überhaupt eine Union? Das ist eher eine Hacker-Datenstruktur und in strukturiertem C und in C++ erst recht eher ungewöhnlich.
    2. Ich wette deine Union ist anders als du denkst. Deine Union enthält entweder ein float[16] oder einen von 16 verschiedenen einzelnen floats unter anderem Namen.
    3. Da fehlen mindestens noch ein paar Semikolons nach der Union-Deklaration und wahrscheinlich willst du dem guten Stück auch noch einen Namen geben.
    4. Was willst du überhaupt erreichen? Wenn es dir darum geht, einzelne Elemente eines Arrays über 2D-Koordinaten anzusprechen, dann gibt es wesentlich robustere Möglichkeiten dafür, ganz ohne die Sprache zu vergewaltigen.



  • Ganz vergessen, die Fehlermeldung 🙄.

    IntelliSense: "class "sipgl::Mat4"" hat keinen Member ""Identity"". mat4.cpp 5 19
    IntelliSense: Zu viele Initialisiererwerte. mat4.cpp 5 31
    


  • SeppJ schrieb:

    1. Warum überhaupt eine Union?
    2. Ich wette deine Union ist anders als du denkst. Deine Union enthält entweder ein float[16] oder einen von 16 verschiedenen einzelnen floats unter anderem Namen.
    3. Was willst du überhaupt erreichen? Wenn es dir darum geht, einzelne Elemente eines Arrays über 2D-Koordinaten anzusprechen, dann gibt es wesentlich robustere Möglichkeiten dafür, ganz ohne die Sprache zu vergewaltigen.

    Zu 1.: damit man entweder mat.m[0] oder mat.m11 schreiben kann, also einfach nur damit man die Möglichkeit hat, den Namen der Stelle explizit anzugeben oder eben einfach nur über einen Index.

    Zu 2.: das ist mir bewusst.

    Zu 3.: siehe 1., man könnte dies auch über Operatorenüberladung [] machen, stimmt, vielleicht sollte ich es so machen

    Aber wie würde es denn gehen?



  • TeaTime schrieb:

    Zu 2.: das ist mir bewusst.

    Bist du dir sicher, dass du verstanden hast, was SeppJ meinte?

    Entweder, du hast ein array von 16 floats oder einen einzelnen(!) float. Nicht 16 floats die auf den 16 Speicherstellen des arrays stehen. Desweiteren bin ich mir gerade nicht einmal sicher, ob du die Union nach Standard C++ so verwenden darfst.



  • Oh verdammt, ja stimmt da ist ja nur ein Float, jetzt verstehe ich was gemeint ist 😮.



  • Gut dann streich ich das einfach mit dem Union und überlade einfach den Operator.

    Vielen Dank!

    mfg


  • Mod

    Das ist doch sowieso reichlich sinnlos, wenn du immer m12 statt m[1][2] (oder m(1,2)) schreiben musst. Denn dann kannst du gar keine Variable als Index a la m(x,y) benutzen. Operatorüberladung und/oder ein kleiner Wrapper um das Array sind der bessere Weg.



  • Ja klar, so gesehen ist es das auch. Nur in der Mathematik heißen die Elemente so, deshalb konnte sich diese "Art" der Implementieren wohl halten, denn die Matrixen in XNA, SlimDX etc. werden tatsächlich so geschrieben. Ich glaub ich werde es einfach so lassen, is ja eigentlich egal ob man nun mat.m11 oder mat[0] schreibt, obwohl ich m11 aussagekräftiger halte, weils in der Mathematik halt so angegeben ist, aber das ist wohl Geschmackssache.



  • fuege doch einfach eine Funktion m(i,j) hinzu.



  • Das ist ja interessant in der DirectXMath API wird das tatsächlich so gemacht, wie ich es ursprünglich vorhatte.

    Hier die XMFLOAT4X4 union.

    union XMFLOAT4X4 {
      union {
        struct {
          float _11;
          float _12;
          float _13;
          float _14;
          float _21;
          float _22;
          float _23;
          float _24;
          float _31;
          float _32;
          float _33;
          float _34;
          float _41;
          float _42;
          float _43;
          float _44;
        };
        float m[4][4];
      };
    };
    

    http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xmfloat4x4(v=vs.85).aspx

    Da is es halt einen Union, es kommt aber das gleiche raus.
    Über den Weg einer Struktur in der Union, so muss man das machen.



  • DirectX ist ja auch ein C-API.



  • DirectXMath ist eine C++-API.

    MS interessiert sich allerdings nur dafür, ob ihr Zeug mit Visual C++ läuft. Laut C++-Standard darf man bei so einer Union doch sowieso nur auf das zuletzt verwendete Feld zugreifen... also aus dem Array lesen, wenn man zuletzt ins Array geschrieben hat und aus dem struct, wenn man zuletzt dessen Member geschrieben hat. Kreuz und quer ist nicht erlaubt. Richtig?

    Mit VC++ funktioniert das also, mit anderen Compilern unter Umständen nicht. Falls das für OP relevant sein sollte.


  • Mod

    nicht ganz schrieb:

    Richtig?

    Richtig. Man sollte aber beachten, dass das eher eine Klausel ist, um bestimmte Sonderfälle (Alignmentprobleme, mit komplexen Datentypen fangen wir lieber gar nicht erst an) abzusichern. Wenn man sich halbwegs auskennt und keine Dummheiten macht, dann funktioniert das mit der Union so wie man erwartet, sogar ziemlich portabel - eher ist die Plattform das Problem als der Compiler. Und wenn man wie der Implementierer von DirectX davon ausgehen kann, dass eine bestimmte Zielplattform vorliegt, dann kann man sich sogar mit Sicherheit drauf verlassen. Insofern ist das schon in Ordnung, das hier so zu machen. Da die Feldgröße anscheinend statisch ist und nicht über das Reihen/Spalten iteriert werden muss, ist das sogar eine einigermaßen brauchbare Idee.


Anmelden zum Antworten