Frage

Ich möchte eine Struktur schaffen, die eine Liste der gleichen Struktur wie folgt enthält:

#include <list>
struct Url
{
    CString strUrl;
    std::list<Url> children;
};

int main()
{
    Url u1, u2;
    u1.children.push_back(u2);
}

Dieser Code kompiliert nicht. Aber wenn ich std::list mit std::vector ersetzen funktioniert es gut. Wie kann ich diese Arbeit mit std::list machen?

Ausgabefenster enthält die folgenden Fehler.

c:\program files\microsoft visual studio\vc98\include\list(29) : error C2079: '_Value' uses undefined struct 'Url'
        E:\test\Test.cpp(23) : see reference to class template instantiation 'std::list<struct Url,class std::allocator<struct Url> >' being compiled
c:\program files\microsoft visual studio\vc98\include\functional(185) : error C2079: 'value' uses undefined struct 'Url'
        c:\program files\microsoft visual studio\vc98\include\list(285) : see reference to class template instantiation 'std::binder2nd<struct std::not_equal_to<struct Url> >' being compiled
        E:\test\Test.cpp(23) : see reference to class template instantiation 'std::list<struct Url,class std::allocator<struct Url> >' being compiled
War es hilfreich?

Lösung

Wenn Sie eine workround für benötigen, was scheint ein VC6 Fehler zu sein, erstellen Sie die Liste dynamisch:

#include <list>
#include <string>     // I don't use MFC

struct Url
{
    std::string strUrl;
    std::list<Url> * children;

    Url() {
       children = new std::list <Url>;
    }

    ~Url() {
        delete children;
    }
};

int  main()
{
    Url u1, u2;
    u1.children->push_back(u2);
}

Einige gefragt haben, warum Listen von der gleichen Art wie Mitglieder sind erlaubt (und meiner Meinung nach sind sie), wenn

Url array[5]; 

zum Beispiel als Mitglied nicht sein. Ich kann nichts im Standard finden entweder, aber sizeof( std:;list <T>) ist nicht abhängig von der Sache ist es eine Liste. Angenommen Liste wurde als (einige Pseudo-C ++ hier) implementiert:

list <T> {
   listEntry <T> * first;
};

dann gibt es keine unbekannte Größe zu behandeln. Betrachten Sie den folgenden minimalen Code, der den Fragesteller Problem behandelt:

template <typename T> struct A {
};

struct B {
    A <B> b;
};

Ich kann nicht jeden möglichen Grund sehen, dass dies nicht legal sein sollte.

Andere Tipps

Können Sie uns sagen, welchen Compiler Sie verwenden? Es ist nichts falsch mit dem, was Sie tun. Ich habe versucht, die folgenden auf VS2008 SP1 und es kein Problem kompiliert

#include <list>

struct Url
{
    std::string name;
    std::list<Url> children;
};

int _tmain(int argc, _TCHAR* argv[])
{
    Url u1,u2;
    u1.children.push_back(u2);
    return 0;
}

Haben Sie vielleicht vergessen Liste enthalten?

Bearbeiten

OP wird mit Visual Studio 6.0 und Neil war in der Lage zu bestätigen, dass es sich tatsächlich um einen Fehler in VS6

Im Gegensatz zu den Behauptungen in den anderen Antworten, es ist in der Tat nicht Rechts jede Standard-Container zu instanziiert, einschließlich std::list, mit einem unvollständigen Typ. (Für eine Diskussion getaggt hierzu siehe zB wie ein unvollständiger Typ kann als Template-Parameter verwendet werden, hier Vektor? )

Diese Anforderung nur in C ++ 17 für std::forward_list, std::list und std::vector entspannt wird. Für jeden früheren Standard, ist der ursprüngliche Code mit neueren Versionen von VC und gcc arbeitet eine Nicht-Standard-Erweiterung. Dies gilt auch für Ihre Beobachtungen mit std::vector.

In Pre-C ++ 17, portably eine std::list einer Klasse T hat als Mitglied der Klasse, Sie brauchen eine Abhilfe wie std::list<T*> oder die boost.container Bibliothek verwenden, die bereits portably die entspannten Anforderungen implementiert.

Hinweis

, dass auch in C ++ 17, Sie können nur die Klassenvorlage instanziiert selbst mit einem unvollständigen Typ. Der Typ muss noch vollständig sein, wenn jedes Mitglied instanziiert wird.

Interessant - Sie versuchen, ein vector oder list unvollständigen Typen zu erstellen. Von einem kurzen Blick auf den Standard, kann ich nichts zu sagen, ob dies oder soll nicht in der C ++ Standard Library enthalten für Containertypen zugelassen werden. Entweder Urteil scheint vernünftig zu sein:

Warum es nicht erlaubt werden könnte. Sie können nicht ein Objekt vom Typ X innerhalb der Definition von X erklären

z. der folgende Code nicht kompilieren, weil es eine unendlich tiefe Datenstruktur schaffen würde:

struct X {
    X x;
};

Warum es erlaubt werden könnte: Die meisten Container sind vergrößerbar, es muss eine Dereferenzierungsebene (Zeiger) auf den tatsächlichen Datenelemente in der Praxis. Es ist legal einen Zeiger-to-X innerhalb der Definition von X zu erklären.

Wie der letzte Absatz schlägt vor, die übliche Art und Weise, um dieses Problem zu bekommen, ist Zeiger oder Verweise zu verwenden, um X. Z.B. die folgenden zwei Schnipsel kompilieren ganz gut:

struct Y {
    Y* y;
};

struct Z {
    std::list<Z*> zl;
    std::vector<Z*> zv;
};

Hat jemand (OK, ich meine litb :-P) wissen, was die Anforderungen sind eigentlich für Standard-Container-Typen?

Der Code sehr gut mit GCC 4.4 kompiliert Und führt perfekt. MSVC ++ vor Version 7 war nicht völlig standardkonform. Sie sollten mit einem neueren Compiler berücksichtigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top