Kann ein Struct sich selbst enthalten?



  • Wohl kaum!

    Du kannst bei rekursiven Datentypen-Definitionen nur mit Zeigern arbeiten.

    struct Typ
    {
        int value;
        vector<Typ*> childs;
    };
    

    Den Speicherplatz (für die einzelnen Struktur-Elemente) mußt du dann mittels new allokieren.



  • EDIT:
    War mal wieder ein Irrglaube...


  • Mod

    Badestrand schrieb:

    So?:

    struct Typ
    {
        vector<Typ> content;
    };
    

    Die Nutzung eines unvollständig definierten Typs bei der Instantiierung einer Templatekomponente der Standardbibliothek führt zu undefiniertem Verhalten (17.4.3.6/2). Lediglich im TR1 gibt es ein paar Ausnahmen (shared_ptr,weak_ptr,enable_shared_from_this).



  • camper schrieb:

    Badestrand schrieb:

    So?:

    struct Typ
    {
        vector<Typ> content;
    };
    

    Die Nutzung eines unvollständig definierten Typs bei der Instantiierung einer Templatekomponente der Standardbibliothek führt zu undefiniertem Verhalten (17.4.3.6/2). Lediglich im TR1 gibt es ein paar Ausnahmen (shared_ptr,weak_ptr,enable_shared_from_this).

    Das verstehe ich nicht, was ist da und wieso unvollständig definiert?


  • Mod

    Badestrand schrieb:

    camper schrieb:

    Badestrand schrieb:

    So?:

    struct Typ
    {
        vector<Typ> content;
    };
    

    Die Nutzung eines unvollständig definierten Typs bei der Instantiierung einer Templatekomponente der Standardbibliothek führt zu undefiniertem Verhalten (17.4.3.6/2). Lediglich im TR1 gibt es ein paar Ausnahmen (shared_ptr,weak_ptr,enable_shared_from_this).

    Das verstehe ich nicht, was ist da und wieso unvollständig definiert?

    Die Definition von Typ ist erst vollständig mit der geschlossenen geschweiften Klammer. Innerhalb der Definition einer Klasse ist diese unvollständig (außer im Körper von Funktionen, Ctor-Memberinitialisierern und Defaultargumenten). Daher kann eine Klasse sich nicht selbst als nichtstatisches Member haben (denn diese werden in einer Klassendefinition definiert, und Objekte dürfen nicht mit unvollständigem Typ definiert werden), wohl aber als statisches Member (diese werden in einer Klassendefinition nur deklariert). In der Definition

    vector<Typ> content;
    

    ist Typ unvollständig; weil dass aber eine Definition ist, wird vector<Typ> (dass selbst vollständig wäre) hier implizit instantiiert, und genau das ist unzulässig.



  • AFAIK ist es nicht grundsätzlich unzulässig ein Template mit einem unvollständigen Typ zu instanzieren, sonst hätte boost::shared_ptr ja ein Problem. Das Problem ergibt sich dadurch dass das instanzierte Template im Fall von std::vector (oder anderen STL Templates) Code enthält der nicht mit unvollständigen Typen klarkommt.

    @camper: interpretiere mein Posting bitte als Frage 🙂


  • Mod

    hustbaer schrieb:

    AFAIK ist es nicht grundsätzlich unzulässig ein Template mit einem unvollständigen Typ zu instanzieren, sonst hätte boost::shared_ptr ja ein Problem. Das Problem ergibt sich dadurch dass das instanzierte Template im Fall von std::vector (oder anderen STL Templates) Code enthält der nicht mit unvollständigen Typen klarkommt.

    richtig. Das sollte aus meinen Texten auch so hervorgehen.



  • Gut. Ich war mir nicht 100% sicher was du gemeint hast, deswegen...
    Danke 🙂



  • camper schrieb:

    hustbaer schrieb:

    Das Problem ergibt sich dadurch dass das instanzierte Template im Fall von std::vector (oder anderen STL Templates) Code enthält der nicht mit unvollständigen Typen klarkommt.

    richtig. Das sollte aus meinen Texten auch so hervorgehen.

    Aber nur implizit. Ich nehme mal an das liegt Assignable und DefaultConstructible.

    edit: was ich schon immer fragen wollte, mich aber nie zu fragen wage ... hast du die Paragraphen im Kopf oder schlägst du nach? 🙂


  • Mod

    finix schrieb:

    camper schrieb:

    hustbaer schrieb:

    Das Problem ergibt sich dadurch dass das instanzierte Template im Fall von std::vector (oder anderen STL Templates) Code enthält der nicht mit unvollständigen Typen klarkommt.

    richtig. Das sollte aus meinen Texten auch so hervorgehen.

    Aber nur implizit.

    Ich nehme mal an das liegt Assignable und DefaultConstructible.

    Soweit würde ich nicht gehen (und für ein Argument, dass diese Bedingungen nicht erfüllt, obwohl es sollte, gibt es eine andere Passage, die das für undefiniert erklärt). Es ist einfach so, dass - wie man sich leicht überlegen kann - viele Templates der Standardbibliothek nur schwierig zu implementieren sind, wenn sie für unvollständige Templateargumente instantiierbar sein sollen. Alle diese Fälle für undefiniert zu erklären, erleichtert die Implementation. Natürlich könnte es Ausnahmen geben - für auto_ptr z.B. wäre das angenehm - aber der Standard tut das nicht. Eine Implementation, die vector mit unvollständigem Argument instantiierbar macht, ist leicht vorstellbar; dies zuzulassen würde aber zum Beispiel eine Optimierung, die bei kleinen Objekten und Vektoren diese ohne zusätzlich Speicherallokiierung im vector-Objekt selbst ablegt (bei std::string kennt man das eher) extrem erschweren. All das ist aber reine Spekulation meinerseits.



  • Mit einem Pointer auf das struct sollte es also gehen?
    Ich werde das heute Abend mal testen.

    Vielen Dank,
    Michael


Anmelden zum Antworten