keine Template-Auflösung und Referenz auf nichts.
-
Hallo,
Ich will eine Variable von einem beliebigen Typ in einem Objekt speichern. Dabei soll aber der Datentyp bereits zur Compile-Zeit überprüft werden.
Mein Versuch sieht folgendermaßen aus:struct saver { template<typename T> void operator()(shared_ptr<T> rhs, T& lhs) { static T subject; if(rhs) subject = *(rhs.get()); lhs = subject; } }; template<typename T> T& dummy() { static T rhs; return rhs; } template<typename T> void save(saver& s, const T& t) { s(new T(t), dummy<T>()); } template<typename T> T get(const saver& s) { T value; s((T*)0, value); return value; }Das klappt soweit in der Verwendung eigentlich auch. Allerdings habe ich bestimmt irgendetwas jetzt übersehen. Deswegen will ich fragen, ob es überhaupt erlaubt ist, so wie ich es gemacht habe. Das gilt vorallem bezüglich der dummy()-Funktion, An der ist bestimmt irgendetwas falsch :p . Die andere Frage ist, dass ich gedacht habe, dass Templates bereits zur Compilezeit überpruft werden. Wenn ich nun also mit der set()-Funktion eine Variable vom falschen Typ übergebe, so meckert der Compiler auch wie gewünscht. Bei der get()-Funktion kompiliert er aber immer, auch wenn der Variablentyp ein falscher wäre.
Es wird übrigens ein Zeiger übergeben, damit ich überprüfen kann, ob er auf nichts zeigt, also ob die interne Variable subject überhaupt verändert werden soll.
Niels
-
Ist es schlimm, wenn ich nicht verstehe was du eigentlich beabsichtigst?
Dummy scheint mir irgendwie keinen Zweck zu haben.Beschreibe mal die Verwendung und Absicht dahinter.
-
nielsp schrieb:
Wenn ich nun also mit der set()-Funktion eine Variable vom falschen Typ übergebe, so meckert der Compiler auch wie gewünscht.
Ich sehe keine set-Funktion, und bei der save()-Funktion sehe ich nicht wo der Compiler meckern sollte.
Bei der get()-Funktion kompiliert er aber immer, auch wenn der Variablentyp ein falscher wäre.
Es gibt keinen falschen Typen. Dein saver-Objekt legt für jeden Typen, für den es aufgerufen wird genau eine statische Variable an, die dann von get immer zurückgegeben wird. Wenn du also im gesamten Programm von deiner saver-Klasse den op() für int, Foo und vector<Bar> aufrufst, dann werden diese 3 Methoden instantiiert. Wenn du dann für ein und dasselbe saver-Objekt einmal op()<int> und einmal op()<Foo> aufrufst, dann legt dieses Objekt für int und Foo eine statische Variable an auf die du per get immer zugreifen kannst.
-
Es gibt keinen falschen Typen.
Typen ohne parameterlosem Konstruktor?
-
Also, mit Dummy will ich eine Referenz von beliebigem Typ erzeugen, da ja mein operator()() von der struct saver() zwei Werte vom selben Typ annimmt, nämlich einen anhand dessen der interne Wert gesetzt werden und ein anderer mit dem der Wert wieder zurückgegeben werden kann. Der Parameter, mit dem es möglich ist, den Wert zu erhalten ist natürlich in der Funktion set() überflüssig. Daher soll der Wert eigentlich einfach ins Nirgendwo geschrieben werden. Ich muss ja aber irgendein Parameter angeben. Daher habe ich mir halt dummy() überlegt.
Niels.
-
Ah, was pumuckl geschrieben hat, dass will mir absolut einleuchten. Ich hänge absolut nicht an meiner Implentierung; gibt es einen alternativen Weg trotzdem die Überprüfung schon während des Compilierens durchzuführen? Übrigens meinte ich mit save() und set() natürlich genau dasselbe.
Niels.
-
nielsp schrieb:
gibt es einen alternativen Weg trotzdem die Überprüfung schon während des Compilierens durchzuführen?
Vielleicht, vielleicht auch nicht. Solang du uns nicht sagst was du wirklich mit dem Ganzen Konstrukt erreichen willst, kann dir keiner helfen.
-
Also, die Sache ist folgendes:
Ich habe eine Basisklasse, die sichCommandnennt und immer eine Funktion zum Ausführen besitzt. Nun soll es aber möglich sein, jederCommandParameter zu übergeben. Jetzt weiß ja aber die Basisklasse nicht, von welchem Typ die Parameter für eine abgeleitete Klasse einmal lauten werden. Deswegen habe ich mir überlegt, dass halt die Zeile mit der Methode zum Ausführen in der Basisklasse folgendermaßen aussehen sollte:virtual void execute(const std::vector<saver>& parameters) = 0;, wobei der Typsavereine Variable von beliebigen Typ enthalten kann.
Ich hoffe das war nun etwas verständlicher. Es soll also praktisch dasselbe sein wie boost::any, mit dem einzigen Unterschied, dass falsche Typen bereits zur Compilezeit erkannt werden können.Niels
-
Wenn du zur Compilezeit nicht weißt, welche Typen die Parameter der abgeleiteten Klassen sind, dann kannst du auch nicht zur Compilezeit feststellen ob übergebene Typen richtig sind.
Wenn der Compiler nicht weiß ob er etwas tun darf (z.B. ob der Typ xy als dritter Parameter richtig ist), kann er auch nicht meckern wenn genau das getan wird.
-
Nimm boost::any.
Ich will garnicht anfangen damit was an deinem Code alles verkehrt ist.