Ich versuche, eine Menge von std :: -Funktion in einer Karte (unter GCC 4.5) zu speichern
Ich möchte 2 Arten von Dingen bekommen:
Ich denke, ich habe den ersten mit einem Klassenbefehl und einem Manager erreicht:
%Vor%kann wie folgt verwendet werden:
%Vor%Nun würde ich gerne in der Lage sein, dies zu tun:
%Vor%Gibt es einen Weg, zB mit type-radition?
Sie können den dynamischen Typ verwenden, um den Typ der Funktion in der Liste zur Laufzeit zu bestimmen. Bitte beachten Sie, dass ich shared_ptr hinzugefügt habe, um das Speicherleck im ursprünglichen Beispiel zu entfernen. Vielleicht möchten Sie eine Ausnahme auslösen, wenn die Methode execute mit den falschen Argumenten aufgerufen wird (wenn die dynamische_Ausgabe 0 ergibt).
Verwendung:
%Vor%Code (mit variadic Vorlagenunterstützung zum Beispiel gcc-4.5):
%Vor%ohne variadische Template-Unterstützung (Beispiel VS2010):
%Vor% Was Sie zu tun versuchen, ist ohne eine ernsthafte Laufzeitarbeit und die damit verbundenen Kosten nicht möglich. Die einfachste Lösung wäre natürlich, einfach eine boost :: any zu speichern ( any_function
hat es nie in boost geschafft) und mache die notwendigen Umwandlungen (oder füge ein paar Laufzeitdaten hinzu, die dir sagen, welche Cast zu machen ist), obwohl du das um jeden Preis vermeiden solltest und mit festen Argumenten oder ohne Argumente gehen solltest.
Ihre Benutzer können dann ihre Funktionen ändern, indem sie bind
verwenden, um sie an die von Ihnen gewünschte Signatur anzupassen.
Bearbeiten: In Ihrem aktuellen Schema sehe ich keinen Grund für CommandManager
, Command*
in der Map zu speichern.
Bearbeiten2: Sie legen auch den Rückgabetyp ab. Dies könnte für Ihren Anwendungsfall in Ordnung sein, macht dies jedoch viel weniger generisch.
Edit3: Ich habe ein funktionierendes Beispiel Ihres Codes mit any
ausgearbeitet. Ich habe das Gefühl, dass es einen Fehler gibt, und ich sehe wirklich nicht, was dies erreichen sollte, aber hier geht es:
Für das Beispiel, das eine feste Signatur verwendet. Denken Sie nur daran, was die natürlichste Darstellung einer Funktion ist, die Sie speichern möchten (wenn Sie Ihr Beispiel Command
betrachten, nehme ich an, dass es std::function<void(void)>
ist). Speichern Sie Funktionen dieses Typs und wann auch immer Ihre Benutzer versuchen, sie zu verwenden Er muss bind
unabhängig von der Funktion, die er verwenden möchte, damit diese Signatur übereinstimmt.
Ihr Command
-Klassenkonstruktor benötigt ein function<void()>
. Sie versuchen es mit einem function<void(string,string)>
zu füttern. Dies wird nicht zum Typcheck.
Wenn Sie Funktionen benötigen, die variable Argumente akzeptieren (wie printf
), benötigen Sie function<>
und execute()
, die variable Argumente akzeptieren. Sie müssen wissen, wie Sie damit arbeiten (insbesondere benötigen Sie ein festes erstes Argument). Sie sind dann für die Typensicherheit verantwortlich, ähnlich wie bei printf
.
Wenn Sie nur eine variable Anzahl von String-Argumenten benötigen, verwenden Sie Funktionen, die z. Vektoren von Strings.
All dies hat mit std::map
überhaupt nichts zu tun. Was immer Sie in einer einfachen alten Variablen speichern können, können Sie auch in std::map
speichern.