schwieriges template? überhaupt möglich?
-
Hallo!
Ich möchte zur Übung eine flexible Klasse für csv-Dateien schreiben. Folgendes habe ich mir dabei überlegt:
- kann aus alle möglichen istreams lesen
- Sie kann verschiedene Datentypen verwalten (auch spaltenweise verschieden).
Das geht, wenn ich ich auch built-in-Typen unterstützen will, nur mit templates. Folgendes dachte ich mir dazu:
Als template gebe ich eine Typelist mit den Datentypen in der Reihenfolge an, wie sie in der Datei auftreten. Die Klasse soll dann jede Zeile einlesen und je nachdem, wie viele spalten ein Typ benötigt (Point2 würde bspw. 2 Spalten benötigen) diese Spalten an den Typen übergeben, welcher diese dann parst und speichert.Ginge das irgendwie? Wie kann ich herausbekommen, ob ein Typ aus der Liste builtin ist, und somit mit boost::lexical_cast gecastet werden kann, oder ob ich den Typen erst fragen muss, wieviele spalten er haben will, und ihm diese dann übergeben zum parsen?
Habt ihr da irgendwelche Vorschläge? Oder meint ihr, dass so eine Klasse unnötig ist? Wies dann in Benutzung aussehen soll, wäre zB so:
typedef csvfile<TypeList2<std::string, Point2D> > mycsvfile; mycsvfile f(std::ifstream("datei.csv")); const mycsvfile::line& line = f.getLine(0); Point2D = line[1]; std::string titel = line[0];Die Datei "datei.csv" sähe dabei zB so aus:
xyz,12.3,14 blabla,1,1csvfile::line muss also auch je nachdem, welchen Index sie bekommt den richtigen Typ zurückliefern, und sollte sich auch verändern lassen mit line[1]=Point2D(1,1); etc.
Ich glaube das ganze wird ein ziemlicher Krampf, wenn es überhaupt geht, oder?
iebe Grüße, Maxi
-
für den einsatz von templates muss der typ immer schon zur compilezeit feststehen, da du die datei aber dynamisch lädst und sich die typen immer ändern können, wird es so nicht funktionieren. in deinem fall heißt das, dass du - sobald du daten aus deiner struktur auslesen willst - du schon beim schreiben deines programms wissen musst, welchen typen du ausgelesen bekommen wirst.
das heißt, alleine aus dem index kannst du den typen nicht bestimmen.es gibt ein paar ganz nette tricks, um das, was du willst, erreichen zu können: nur werden dir - bei fehlschlag - keine compilerfehler geliefert, sondern du musst zur laufzeit auf fehler reagieren.
beispielsweise könntest du deiner klasse für jeden Typ aus der TypeList einen
operator Typspendieren. ohne variadic templates ist das dann für (fast) beliebig lange typlisten zwar ein großer aufwand, aber nicht unmöglich.schau dir zu dem thema einmal boost::variant an.
eine andere möglichkeit, vorzugehen, zeigt dir boost::any. IIRC kannst du mit einer bestimmten get-methode/funktion auf das objekt (beliebigen typs) in any zugreifen, in der art
get<std::string>(csvfile)für dich.aber wie gesagt, die typ-checks sind frühestens zur laufzeit möglich.
-
Hi Maxi,
Was du da machen möchtest ist in der Tat möglich und keine Utopie. Ich würde gar nicht erst an boost::lexical_cast denken sondern eher darauf bauen das es operator >> überladungen für die Typen gibt.
Das und dazu dann ein boost::tuple intern und alles ist super

Aber was ich nicht so gut finde ist das hier:
const mycsvfile::line& line = f.getLine(0);Ich würde da eher zu einem Iteratoren Interface tendieren anstatt in der datei dann immer hin und her zu seeken um die Zeile zu finden.
BR
Vinzenz