std::function generisch speichern
-
Hi,
ich würde gerne std::function verschiedenen Typs einheitlich speichern, zB. in einer std::map.
Zwei Ansätze habe ich, doch beim Zweiten weiß ich nicht, ob das legales C++ ist (oder vielleicht UB *fürcht*):
// 1. Ansatz std::function<void()> ff; Derived* d; void Save(const std::function<void(Derived*)>& f) { ff = [f]{ f(d); }; } void Call() { d = new Derived; ff(); }
// 2. Ansatz std::function<void(Base*)> ff; void Save(const std::function<void(Derived*)>& f) { ff = reinterpret_cast<const std::function<void(Base*)>&>(f); // ist das OK? } void Call() { ff(new Derived); }
// Benutzung Save([](Derived* d) { cout << "DER: " << d->b << endl; }); Call();
Was meint ihr?
Der Code dient natürlich nur zur Veranschaulichung.
Danke!
-
Was ist überhaupt dein Ziel? Eine
std::function
mit einem Parameter zu einer mit keinen Parametern, vonstd::function<void(Base*)>
zustd::function<void(Derived*)>
oder von Derived zu Base? Wenn du die Anzahl der Parameter ändern willst ist verpacken in eine Lambda Funktion schon das richtige. Nur mit der globalen Variable ist unschön. Derreinterpret_cast
ist böse und sorgt mit großer Sicherheit für einen Absturz in deinem Programm. Die Konvertierung von Base zu Derived scheint übrigens automatisch zu funktionieren. Anders herum brauchst du wieder eine Lambda Funktion.
-
Ich möchte Lambdas mit verschiedenen Derived-Typ-Parametern für einen späteren Aufruf in einer std::map speichern.
Dabei soll der Funktion ein Lambda mit Derived* Parameter übergeben werden, damit ich nicht immer...
Save([](Base* b) { Derived* d = static_cast<Derived*>(b); // ...dies... cout << "DER: " << d->b << endl; });
...schreiben muss.
Die Funktion ist eigentlich ein Template, und die globale Variable dient, wiegesagt, nur zur Veranschaulichung.
Warum Absturz? Ich stelle schon sicher, dass immer ein Objekt mit korrektem Typ übergeben wird.
-
Dann pack die Konvertierung zu Derived doch in der Save Funktion dazu:
void Save(const std::function<void(Derived*)>& f) { ff = [f](Base* b) { f(static_cast<Derived*>(b)); }; }
Miau schrieb:
Warum Absturz? Ich stelle schon sicher, dass immer ein Objekt mit korrektem Typ übergeben wird.
Du Konvertierst aber einfach Referenzen auf
std::function
zu einemstd::function
mit anderen Template Parametern. Dankreinterpret_cast
frisst der Compiler alles. Du könntest damit auch ein int zu einer Referenz auf einestd::function
casten. Ich habe deine Variante 2 gerade mal getestet und es gab sogar das erwartete Verhalten. Allerdings ist das keinesfalls garantiert und spätestens mit Mehrfachvererbung oder Polymorphie, wo es zwischen Pointer auf Base und Derived einen Offset geben kann, wird es sowieso nicht mehr wie gewünscht funktionieren.
-
Ja, ich wollte bloß wissen, ob der std::function-cast OK ist...
Aber war wohl ne blöde IdeeHabe es jetzt mit dem zwischen-lambda (1. Ansatz) gelöst, musste nun außerdem doch unterschiedliche Parameteranzahlen unterstützen.
Das neue C++ ist schon geil