Ich erstelle eine Klasse namens MessageableObject, die eigene Memberfunktionen in einer Zuordnung registrieren kann. Diese Funktionen können von außen aufgerufen werden, indem sendMessage aufgerufen wird, ein Rückgabetyp als Vorlagenparameter bereitgestellt wird und der Name der Funktion sowie die Parameter als variadische Argumente übergeben werden. Ich habe etwas gesehen, das dem vorher sehr ähnlich ist, nur die Funktionen waren nicht Mitgliedsfunktionen der Klasse, die sie speichert.Speichern und Aufrufen einer unordered_map von Memberfunktionen mit unterschiedlichen Signaturen
Unten ist der Code, den ich bisher geschrieben habe, sowie ein Testfall, der erfolgreich sein sollte.
#include <iostream>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
class MessageableObject
{
using _message_ptr = void(MessageableObject::*)(void);
std::unordered_map<const char*, std::pair<_message_ptr, std::type_index>> _message_map;
public:
MessageableObject()
{
}
template<typename F>
void addMessage(const char* name, F func)
{
auto type = std::type_index(typeid(func));
_message_map.insert(std::make_pair(name, std::make_pair((_message_ptr)func, type)));
}
template<typename R, typename... Args>
R sendMessage(const char* name, Args&&... args)
{
auto iter = _message_map.find(name);
assert(iter != _message_map.end());
auto type = iter->second;
auto func = reinterpret_cast<R(MessageableObject::*)(Args ...)>(type.first);
assert(type.second == std::type_index(typeid(func)));
return func(std::forward<Args>(args)...);
}
void foo()
{
std::cout << __FUNCTION__ << std::endl;
}
int bar(int i, int j)
{
std::cout << __FUNCTION__ << ' ' << i + j << std::endl;
return i + j;
}
};
int main()
{
MessageableObject obj;
obj.addMessage("foo", &MessageableObject::foo);
obj.addMessage("bar", &MessageableObject::bar);
obj.sendMessage<void>("foo");
int baz = obj.sendMessage<int>("bar", 1, 2);
return 0;
}
Derzeit erzeugt dieser Code den folgenden Fehler zweimal:
C2064: Ausdruck ergibt keine zu einer Funktion unter n Argumente
Das erste Mal mit n 0 ist wenn ich versuche, foo
anzurufen, und n 2 ist, wenn ich versuche, bar
aufzurufen. Warum treten diese Fehler auf? Und kann ich das auch mit der aktuellen Syntax umsetzen? Jedwedes https://stackoverflow.com/a/33837343/962805
Hilfe geschätzt stark:
Als Referenz die Version dieser Implementierung, die auf nicht-Member-Funktionen arbeitet, kann hier gefunden werden. Ich bin nicht sehr gut informiert über Typ-Löschung und Bindung von Member-Funktionen. Die Absicht dafür ist, die Funktion GameObject.sendMessage
für dynamische Nachrichtenübermittlung der Einheitseinheit zu erstellen.
Aktualisierung: Wie nach der Antwort von skypjack unten wird die obige Lösung brechen, wenn der Nachrichtenaufruf eine Variable enthält. Sie kann behoben werden, indem Sie in sendMessage Args&&...
in Args...
ändern, jedoch stellt dies ein neues Problem dar: Wenn der Map eine Nachricht hinzugefügt wird, die einen Referenzparameter enthält (z. B. int bar(int&, int)
), kann sie nicht implizit aufgerufen werden. Der Aufruf von sendMessage<int, int&, int>("bar", x, 2)
funktioniert wie vorgesehen.
Vielen Dank! Diese Lösung kompiliert und funktioniert tatsächlich. Jetzt muss ich nur eine robustere Lösung finden, um Variablen als Argumente zu behandeln und UB zu vermeiden. – dyeo