Kürzlich habe ich viele Probleme mit typedef und unvollständigen Typ, wenn ich bestimmte Container, Allokatoren in meinem Code geändert habe.
Was ich vorher hatte
%Vor% Obwohl nicht ganz sicher, ob die obigen Zeilen legal sind, aber das hat bei jeder Implementierung funktioniert, die ich verwendet habe. Als ich dachte, dass ich den Job mit std::tr1::array
machen kann, änderte ich die obigen zwei Zeilen mit
Hier bricht alles zusammen, da der Compiler versucht, array
zu instanziieren und fehlschlägt, da foo
unvollständiger Typ ist. Alles, was ich brauchte, ist ein Verweis auf foo
, und wenig Interesse an 'anderen Teilen' des Arrays. foo wird definitiv vollständig verfügbar sein, wenn ich ein solches Array erstelle.
Das gleiche Problem tritt auf, wenn typedef std::allocator<foo>::pointer foo_ptr
durch typedef stack_alloc<foo,10>::pointer foo_ptr
ersetzt wurde. wo eine stack_alloc
Implementierung ist wie
Angenommen, value_type
, pointer
, reference
, iterator
usw. hängen nicht von der Vollständigkeit von T
ab, und wissen, dass die Klasse nicht ohne vollständigen Typ instanziiert werden kann, wie dies typedef kann in generischer Weise unabhängig von einem bestimmten Container oder Allokator gemacht werden?
HINWEIS:
vector
, anstatt ihn durch std::array
zu ersetzen, obwohl das Problem gleich bleibt. stack_alloc
code ist bei weitem nicht vollständig und zeigt nur den Teil des Problems an. all_foos
mit unvollständigem foo
. struct foo{ foo_ptr p;};
nicht definiert werden. Obwohl foo_ref
möglicherweise nicht anders als foo&
, aber foo_ptr
sein kann. Überraschenderweise hat die GCC-Implementierung keinen verschachtelten Zeigertyp für tr1::array
. Ein Typ muss vollständig sein, damit er in einem Standardcontainer verwendet werden kann, oder das Verhalten ist nicht definiert (§17 .4.3.6 / 2). Also ist die einzige Standardlösung, das typedef
nicht zu machen, bis die Klasse definiert ist.
Ich verstehe nicht, wofür der Zwischenbehälter ist:
%Vor% In jedem Fall müssen Sie zuerst den vollständigen Typ definieren. Um ein typedef
in einer Klasse zu definieren, muss diese Klasse muss instanziiert werden, was bedeutet, dass die gesamte -Datei T
wie gewünscht verwenden kann.
Beispiel: stack_alloc
muss T
einen vollständigen Typ haben (damit sizeof(T)
funktioniert), andernfalls kann die Klasse nicht instanziiert werden. Wenn die Klasse nicht instanziiert werden kann, kann die typedef
nicht abgerufen werden. Ergo, Sie werden niemals die typedef
davon erhalten, wenn T
unvollständig ist.
Der Compiler kennt die Größe des unvollständigen Typs nicht, deshalb kann er ihn nicht instanziieren und ihm auch keinen Speicher zuweisen. Wenn Sie einen Zeiger auf das Objekt (wie typedef std::tr1::array<foo*, 5> all_foos;
) anstelle der Instanz des Objekts selbst haben, wird dieses Problem gelöst.