2016-05-12 5 views
2

Ich habe ein Programm in C++ geschrieben, das mit clang ++ kompiliert, aber nicht mit g ++, und ich würde gerne verstehen, warum. dieseSTL-Container, der die Klasse innerhalb der Deklaration dieser Klasse enthält

Der wesentliche Teil ist:

class Table { 
    private: 
     ... 
     std::unordered_map<std::string,Table> table_map; 
     ... 
}; 

Ich dachte, dass std :: unordered_map mit Zeigern "unter der Haube" sein würde, so dass diese legal ist. Ich deklariere keine Tabelle innerhalb einer Tabelle, aber ich erstelle einen Container, der Zeiger auf die Tabelle (n) innerhalb einer Tabelle hat. So dachte ich. Clang ++ hat damit kein Problem und das Programm läuft gut.

Allerdings beklagt sich g ++ darüber und sagt "note: forward declaration of 'class Table'". Dies legt nahe, dass ich die std :: unordered_map explizit dazu bringen sollte, einen Zeiger (std::unordered_map<std::string,Table*>, oder vielleicht einen Geschmack von Smart Pointer) zu nehmen. Das erfordert, dass ich etwas mehr Arbeit mache (und ich beschäftige mich mit Code, den ich vor über einem Jahr geschrieben habe, also bin ich nicht begierig darauf, herauszufinden, was ich getan habe, um die notwendigen Änderungen vorzunehmen).

Ist das ein Bug in g ++ oder ist C++ ein etwas cleveres, das nicht wirklich Teil des Standards ist? Gibt es eine bessere Möglichkeit, diesen Code neu zu schreiben, so dass er sowohl in clang ++ als auch in g ++ kompiliert?

Ich habe eine andere Klasse namens Value, und es gibt eine std :: unordered_map von Werten innerhalb der Tabelle, so würde ich dieses Problem umgehen, indem Sie eine Oberklasse Element, aus dem Wert und Tabelle erben, und dann Tabelle enthält eine ? Oder wäre eine solche Karte nicht in der Lage, Werte und Tabellen zu speichern, weil sie für Elemente deklariert wurde?

+4

Es gibt Pläne nicht unterstützt: : list' und 'std :: forward_list', um unvollständige Typen zu unterstützen, aber noch nicht' std :: unordered_map'. Vielleicht unterstützt Boosts Karte es. – chris

Antwort

4

Der Fehler wird dadurch verursacht, dass std :: unordered_map die Tabelle erneut anzeigen und dann Elemente kopieren muss. Der im Container gespeicherte Wert muss daher ein vollständiger Typ sein.

Sie können darüber hinwegkommen, indem Wert in intelligenten Zeiger Verpackung:

#include <iostream> 
#include <string> 
#include <unordered_map> 
#include <memory>   // shared_ptr 

class Table { 
    private: 
    std::unordered_map<std::string, std::shared_ptr<Table> > t; 
}; 

int main() { 
    Table t; 
    return 0; 
} 

Compiles.

+0

'unique_ptr

' ist natürlich auch möglich –

2

Dies ist ein undefiniertes Verhalten. Standardbibliothekscontainer können nicht mit unvollständigen Typen instanziiert werden, es sei denn, es wird explizit angegeben, dass der Container dies unterstützt (z. B. unique_ptr).

Optionen sind verfügbar:

  • Code Redesign nicht dieses
  • Verwenden Sie ein Container-Bibliothek tun, die dies für `std :: VECTOR`, std
Verwandte Themen