POD/Trivial/Standard Layout?



  • Hallo zusammen,

    ich habe hier diese struct

    struct Vertex
    {
    	unsigned int	     FileID		= 0;
    	unsigned int 	     ParcelID           = 0;
    	unsigned __int64     Timestamp          = 0;
    	float                Value	        = 0.0f;
    	float                RelativePosition	= 0.0f;
    	float                AbsolutePosition	= 0.0f;
    };
    

    Sowohl std::is_pod<Vertex>::value, std::is_trivial<Vertex>::value und std::is_standard_layout<Vertex>::value sind false. Warum?



  • schätze wg __int64
    Möglicher Grund könnten aber auch die Initialisierungen sein, für die der Compiler einen Konstruktor erstellen muß.



  • @DocShoe
    So wie es aussieht ist ein Struct nicht mehr TrivialType, wenn die Member initialisiert werden.

    Probiere mal folgendes aus:

    #include <stdio.h>
    #include <string.h>
    #include <type_traits>
    
    
    struct Vertex
    {
    	unsigned int	     FileID = 0;
    	unsigned int 	     ParcelID = 0;
    	unsigned __int64     Timestamp = 0;
    	float                Value = 0.0f;
    	float                RelativePosition = 0.0f;
    	float                AbsolutePosition = 0.0f;
    };
    
    struct Vertex2
    {
    	unsigned int	     FileID;
    	unsigned int 	     ParcelID;
    	unsigned __int64     Timestamp;
    	float                Value;
    	float                RelativePosition;
    	float                AbsolutePosition;
    };
    
    // Debug code
    int main()
    {
    	auto b1 = std::is_pod<Vertex>::value;
    	auto b2 = std::is_pod<Vertex2>::value;
    	
    	auto b3 = std::is_trivial<Vertex>::value;
    	auto b4 = std::is_trivial<Vertex2>::value;
    
    	auto b5 = std::is_standard_layout<Vertex>::value;
    	auto b6 = std::is_standard_layout<Vertex2>::value;
    	
    	return 0; // Breakpoint setzen
    }
    


  • Danke euch beiden, es liegt an der Standardinitialisierung, wenn ich die weglasse liefern die type_traits true zurück.
    Gibt es eine Möglichkeit, Standardinitialisierung zu benutzen und gleichzeitig sicherzustellen, dass Sachen wie memset garantiert erlaubt sind?



  • @DocShoe
    Man könnte es mal mit std::is_trivially_copyable probieren.

    Denn die Doku zu std::memset sagt:

    If the object is a potentially-overlapping subobject or is not TriviallyCopyable (e.g., scalar, C-compatible struct, or an array of trivially copyable type), the behavior is undefined.


  • Mod

    Du solltest deine eigenen Annahmen hinterfragen. Wenn es Sinn macht, dass die Member eine explizite Defaultinitialisierung haben, dann ist es halt kein POD. Für mich sieht es aber eher so aus, als ob die von dir vorgegebenen Werte nicht zu der durch den Namen implizierten Semantik passen. Das Objekt ist doch mit dieser Defaultinitialisierung gewiss gar nicht funktionsfähig. Was soll also der Defaultwert, wenn man sowieso alle Member nochmals initialisieren muss, bevor man das Objekt sinnvoll benutzen kann?



  • @Quiche-Lorraine :
    Mit std::is_trivially_copyable geht´s, die Gegenprobe mit `nem zusätzlichen String schlägt fehl.

    @SeppJ
    Hab mir halt angewöhnt, alles zu initialisieren. Im Prinzip hast du aber recht.



  • Hab mir halt angewöhnt, alles zu initialisieren.

    Gute Idee, ich auch. Das macht man aber m. E. nach besser so:

    #include <cstdint>
    #include <iostream>
    
    struct Vertex
    {
    	unsigned int	      FileID;
    	unsigned int 	      ParcelID;
    	std::uint64_t         Timestamp;
    	float                 Value;
    	float                 RelativePosition;
    	float                 AbsolutePosition;
    };
    
    int main() {
        Vertex v{};
        Vertex* pv{ new Vertex{} };
        
        std::cout << v.FileID << '\n'; // 0
        std::cout << pv->FileID << '\n'; // 0
        
        delete pv;
    }
    

    Ich verstehe auch nicht, warum man hier nicht std::uint64_t aus der Standardbibliothek verwenden würde. Aber ist ja wohl nur Nebensache.

    Finde die Syntax mit {} um mit Nullen zu initialisieren eigtl. sehr angenehm, wenn man weiß was es bedeutet.

    Was soll also der Defaultwert, wenn man sowieso alle Member nochmals initialisieren muss, bevor man das Objekt sinnvoll benutzen kann?

    Ich weiß nicht, wie es dabei anderen geht, aber ich finde es immer noch besser ein Objekt in einem deterministisch nicht funktionsfähigen Zustand zu haben, als in einem uninitialisierten (zufälligen), nicht funktionsfähigen Zustand (oder sporadisch eben doch funktionsfähig).


  • Mod

    @DocShoe sagte in POD/Trivial/Standard Layout?:

    @SeppJ
    Hab mir halt angewöhnt, alles zu initialisieren. Im Prinzip hast du aber recht.

    Ich glaube Du verstehst ihn falsch. Er sagt nicht, dass nicht alles initialisiert werden muss (was fuer sich ebenfalls korrekt ist, aber vorsichtig begruendet werden muss), sondern dass man Objekte erst zu einem Zeitpunkt erstellen koennen sollte, zu dem die Initialwerte bereits bekannt sind. Das heisst, keine Default-Werte, sondern einen Konstruktor.
    Triviale Kopierbarkeit wird von deiner Klasse indes erfuellt, also brauchst Du dir bzgl. low-level Operationen nicht zu viele Gedanken machen.


Log in to reply