Ich schreibe einige Vorlagenklassen zum Parsen einiger Textdatendateien, und als solche ist es wahrscheinlich, dass die große Mehrheit der Analysefehler auf Fehler in der Datendatei zurückzuführen ist, die größtenteils nicht von Programmierern geschrieben wurden und daher benötigt werden eine nette Nachricht darüber, warum die App nicht geladen werden konnte, zB so etwas wie:
Fehler beim Parsen von example.txt. Der Wert ("notaninteger") des Schlüssels [MySectiom] ist kein gültiger int
Ich kann die Datei-, Abschnitts- und Schlüsselnamen aus den Argumenten ermitteln, die an die Vorlagenfunktion und die Mitgliedsvariablen in der Klasse übergeben wurden. Ich bin mir jedoch nicht sicher, wie ich den Namen des Typs ermitteln soll, in den die Vorlagenfunktion konvertieren möchte.
Mein aktueller Code sieht so aus, mit Spezialisierungen für einfache Zeichenfolgen und dergleichen:
template<typename T> T GetValue(const std::wstring §ion, const std::wstring &key)
{
std::map<std::wstring, std::wstring>::iterator it = map[section].find(key);
if(it == map[section].end())
throw ItemDoesNotExist(file, section, key)
else
{
try{return boost::lexical_cast<T>(it->second);}
//needs to get the name from T somehow
catch(...)throw ParseError(file, section, key, it->second, TypeName(T));
}
}
Ich muss lieber nicht für jeden Typ, den die Datendateien verwenden, bestimmte Überladungen vornehmen, da es viele davon gibt ...
Außerdem benötige ich eine Lösung, die keinen Laufzeitaufwand verursacht, es sei denn, eine Ausnahme tritt auf, dh ich möchte eine Lösung zur vollständigen Kompilierungszeit, da dieser Code tonnenweise aufgerufen wird und die Ladezeiten bereits etwas lang werden.
EDIT: Ok, das ist die Lösung, die ich mir ausgedacht habe:
Ich habe einen Typ, der Folgendes enthält
#pragma once
template<typename T> const wchar_t *GetTypeName();
#define DEFINE_TYPE_NAME(type, name) \
template<>const wchar_t *GetTypeName<type>(){return name;}
Dann kann ich das Makro DEFINE_TYPE_NAME verwenden, um CPP-Dateien für jeden Typ zu erstellen, mit dem ich mich befassen muss (z. B. in der CPP-Datei, die den Typ definiert, mit dem begonnen werden soll).
Der Linker kann dann die entsprechende Spezialisierung finden, solange sie irgendwo definiert wurde, oder andernfalls einen Linkerfehler auslösen, damit ich den Typ hinzufügen kann.