VS2010 Bug?
-
Hallo,
folgender Code bereitet mir in VS2010 Probleme:
template <typename Type, typename Param> class EventHandler { private: class Handler { public: typedef void (Handler::*Type)(Param); Handler *source; Type function; }; public: template <typename T> void Add(void *source, T function) { Handler h; h.source = reinterpret_cast<Handler*>(source); h.function = reinterpret_cast<Handler::Type>(function); ... } ... }; class Test : std::enable_shared_from_this<Test> { public: EventHandler<void(const std::shared_ptr<Test> &), const std::shared_ptr<Test> &> e; Test() { e.Add(this, &Test::func); } virtual ~Test() { } void func(const std::shared_ptr<Test> &p) { } };Fehlermeldung:
Error 1 error C2440: 'reinterpret_cast' : cannot convert from 'void (__thiscall Test::* )(const std::tr1::shared_ptr<_Ty> &)' to 'void (__thiscall EventHandler<Type,Param>::Handler::* )(Param)'Problem lässt sich lösen, wenn man entweder die Klasse Test nicht virtual macht oder std::enable_shared_from_this<Test> weglässt.
In ideone kompiliert der Code ohne Fehler (http://ideone.com/WG7f8).
Bug in VS2010 oder ideone?
greetz KN4CK3R
-
Reinterpret_cast macht an der Stelle mit Sicherheit nicht das, was du erreichen willst.
Warum willst du ein void* übergeben und irgendein T, damti verlierst du wertvolle Typinformationen. z.B. würde folgendes "gehen":int i; eventHandler.Add(&i, i);Was willst du erreichen?
-
mit Add lassen sich Funktionen einer Klasse dem EventHandler zuweisen. Per Invoke können diese dann von einer anderen Stelle aufgerufen werden.
void Invoke(Param param) { for (auto it = handlers.begin(); it != handlers.end(); it++) { Handler &handler = *it; (handler.source->*handler.function)(param); } }Also verschiedene Funktionen registrieren und dann per Invoke alle nacheinander aufrufen.
Test t; t.e.Invoke(0); //ruft Test::func(0) aufgreetz KN4CK3R
-
MSVC 2010 kennt da schon schöne und nützliche Features des C++0x Standard: std::function und Lambdas. Damit sieht dein Code wie folgt aus:
template <typename Signature> class EventHandler { typedef std::function<Signature> Handler; std::vector<Handler> handlers; public: void Add(Handler const& h) { handlers.push_back(h); } template <class T> void invoke(T&& param) { for (auto it = handlers.begin(); it != handlers.end(); ++it) { Handler& h = *it; h(std::forward<T>(param)); } } }; class Test : std::enable_shared_from_this<Test> { public: EventHandler<void(const std::shared_ptr<Test> &p)> e; Test() { e.Add([this](const std::shared_ptr<Test> &p) { func(p); }); //alternativ: // e.Add(std::bind(&Test::func, this, std::placeholders::_1)); } virtual ~Test() { } void func(const std::shared_ptr<Test> &p) { } };
-
Irgendwie schein Laufzeitpolymorphie durch Vererbung und virtuelle Funktionen aus der Mode zu kommen.
-