C++ std::map-template-Klasse Werte
Versuche ich zu erklären, eine Row
und ein Column
Klasse, mit der Row
mit einem privaten std::map
mit Werten Hinweis auf eine vorgefertigte Column
. So etwas wie dieses:
template <typename T>
class DataType {
private:
T type;
};
template <typename T>
class Field {
private:
T value;
DataType<T> value;
};
class Row {
private:
std::map<unsigned long,Field*> column;
};
Naja, ich denke, im Prinzip ist die Row
Klasse sollte nicht wissen, welche Art von Field
(oder Column
) wir verwenden möchten, d.h. ob es ein Field<int>
in Spalte 1 oder eine Field<double>
in Spalte 2. Aber ich bin mir nicht sicher, was die korrekte syntax für die Row::column
Erklärung, oder wenn die std::map
in diesem begrenzten Sinn, und ich sollte über etwas anderes.
Ich appretiate Sie Anregungen und danke Ihnen im Voraus.
InformationsquelleAutor der Frage jbatista | 2009-02-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Field
allein ist kein Typ, sondern eine Vorlage generieren kann eine Familie von Typen, wieField<int>
undField<double>
. Alle diese Felder sind nicht miteinander verwandt, so dass Sie die eine ist irgendwie abgeleitet von der anderen oder so. So müssen Sie zum herstellen einen Bezug zwischen diesen generierten Typen an. Eine Möglichkeit ist die Verwendung einer gemeinsamen nicht-template-Basisklasse:Und betrachten Sie die Verwendung von smart-pointer statt, die raw-Zeiger in den code. Anyway, das problem ist jetzt, dass die Typ-Informationen verloren gehen - egal, ob Sie zu einem Punkt
Field<double>
oder eineField<int>
ist nicht mehr bekannt und kann nur erkannt werden, indem Sie einige Sortieren von Typ-flag in die base, welche festgelegt ist durch die Vorlagen abgeleiteten Klasse oder von Fragen, RTTI mitAber das ist hässlich. Vor allem, weil das, was Sie wollen, gibt es einen semantischen Wert. I. e Sie möchten, um der Lage sein, kopieren Sie die Zeilen, und es würde kopieren Sie alle it-Bereiche. Und Sie möchten, um eine doppelte, wenn ein doppelt gespeichert ist - ohne zuerst mit RTTI-hack Ihren Weg zu den abgeleiteten Typ.
Einen Weg, es zu tun, ist die Verwendung einer besonderen union. Das ist im Grunde eine union für einige beliebige Typen und zusätzlich ein Typ-flag, das speichert, was Wert ist aktuell gespeicherte Feld (e -.g, ob ein double, int, ...). Zum Beispiel:
boost::variant macht die ganze Arbeit für Sie. Sie können visitation zu machen, nennen einen Funktor mit der rechten überlastung. Haben Sie einen Blick auf seine Handbuch
InformationsquelleAutor der Antwort Johannes Schaub - litb
Nun, um Ihre Frage zu beantworten :), Feld<> Klassen Erben von einer gemeinsamen Basisklasse, die von allen Datentypen. Diese Möglichkeit, einen container wie Ihre Spalte anzeigen kann, halten Zeiger (das gemeinsamen Zeiger) auf abgeleitete Objekte, die Instanzen der template-Klasse.
InformationsquelleAutor der Antwort Assaf Lavie
Einen
Row< int, float, int>
ist wirklich anders, eineRow<int, std::string>
.Klar,
Row<int,float,int>.field<0>
sollte einField<int>
währendRow<int,float,int>.field<1>
sollte einField<float>
. UndRow<int,float,int>.field<3>
ist ein compiler-Fehler.Der einfachste Weg, dies zu tun ist mit Boost. Eine ganze Menge von der Intelligenz wurde erstmals von Loki (siehe Modern C++ Designvon Andrei Alexandrescu) aber Steigern ist moderner und besser unterstützt.
Normalerweise würden Sie nicht die Iteration über die Felder - jedes Feld hat seinen eigenen Typ. Aber Sie tun, Sie würde wirklich brauchen eine
FieldBase
. Wenn Sie brauchen, eine solche Schnittstelle, ist es wahrscheinlich lohnt zu speichern die Felder intern alsboost::array<FieldBase, N>
(d.h.Row<int,float,int>
hat eineboost::array<FieldBase, 3>
). Sie sollten nie müssendynamic_cast
dassFieldBase*
obwohl. Das ist ein Laufzeit-test, und Sie immer wissen, die genaueT
jederField<T>
zur compile-Zeit.InformationsquelleAutor der Antwort MSalters