c++ 11 Event implementation



  • @Swordfish sagte in c++ 11 Event implementation:

    Weißt was? Wenn Du Dir vor zwei Wochen die Mühe gemacht hättest den Artikel den ich Dir in der ersten Antwort gegeben habe zu lesen, hättest Du das Konzept sicher schon verstanden.

    Hier traut man sich bald nichts mehr zu fragen.

    Du meinst diesen hier:
    C++11 Generic Observer-Pattern

    Gelesen habe ich ihn. Aber ich habe daraus mein Problem nicht lösen können. Sorry.

    Th69 schreibt ja auch
    "irgendwie hat der Code mit using std::placeholders vorher nicht kompiliert "
    mir ging es auch so.

    Ich hatte zunächst mit eurer Hilfe das std::bind verwendet und this nicht dereferenziert.
    Hat nicht kompiliert. Dann ein Beispielprojekt gemacht und darin this dereferenziert so wie es th69 gesagt hat.
    Beispielprojekt hat kompiliert also auch im richtigen Projekt dereferenziert. Und da tat es nicht.

    Erst als ich dann nochmals das richtige Projekt verändert habe um den Fehler zu suchen und dabei die Dereferenzierung weggenommen habe hat es funktioniert.

    Ist das jetzt ein Grund mir solche Vorwürfe zu machen?



  • @booster sagte in c++ 11 Event implementation:

    "irgendwie hat der Code mit using std::placeholders vorher nicht kompiliert "
    mir ging es auch so.

    Ach komm. Der Code aus dem Artikel kompiliert mit Visual Studio 2017 - Windows XP (v141_xp) ohne jegliche Änderung.

    #include <iostream>
    #include <string>
    #include <functional>
    #include <list>
    
    template <typename... Args>
    class Dispatcher
    {
    public:
    	typedef std::function<void(Args...)> CBType;
    
    	class CBID
    	{
    	public:
    		CBID() : valid(false) {}
    	private:
    		friend class Dispatcher<Args...>;
    		CBID(typename std::list<CBType>::iterator i)
    			: iter(i), valid(true)
    		{}
    
    		typename std::list<CBType>::iterator iter;
    		bool valid;
    	};
    
    	// register to be notified
    	CBID addCB(CBType cb)
    	{
    		if (cb)
    		{
    			cbs.push_back(cb);
    			return CBID(--cbs.end());
    		}
    		return CBID();
    	}
    
    	// unregister to be notified
    	void delCB(CBID &id)
    	{
    		if (id.valid)
    		{
    			cbs.erase(id.iter);
    		}
    	}
    
    	void broadcast(Args... args)
    	{
    		for (auto &cb : cbs)
    		{
    			cb(args...);
    		}
    	}
    
    private:
    	std::list<CBType> cbs;
    };
    
    
    
    using namespace std;
    
    // a dummy enum for this example
    enum EventEnum { EVENT1, EVENT2, EVENT3 };
    
    int main(int argc, char *argv[])
    {
    	// 2 example dispatchers, any number of arguments and types can be used:
    	Dispatcher<string, EventEnum> d1;// here any cb(string, EventEnum) can register
    	Dispatcher<int, long, double> d2;// here any cb(int, long, double) can register
    
    	// From the "most simple" lambda usage example ...
    
    	auto cbid1 = d1.addCB([](string str, EventEnum evt) {
    		cout << "CB1:" << str << " got event " << evt << endl;
    	});
    	auto cbid2 = d1.addCB([](string str, EventEnum evt) {
    		cout << "CB2:" << str << " got event " << evt << endl;
    	});
    
    	d1.broadcast("** Dispatching to 2 is **", EVENT1);
    	d1.broadcast("**       E a s y       **", EVENT2);
    
    	d1.delCB(cbid1); // remove the first callback
    	d1.broadcast("** Dispatching to 1 is **", EVENT1);
    	d1.broadcast("**       E a s y       **", EVENT2);
    
    	d1.delCB(cbid2); // remove the second callback
    	d1.broadcast("** No one will see this **", EVENT3);
    
    	// ... to the "most complex" **live** instance (not copy) usage example:
    
    	class MyClassWithMethod {
    	public:
    		void registerCB(Dispatcher<int, long, double> &dispatcher) {
    			using namespace std::placeholders;
    			dispatcher.addCB(std::bind(&MyClassWithMethod::listener, this, _1, _2, _3));
    		}
    	private:
    		// any method with the right signature can be used:
    		void listener(int i, long l, double d) {
    			cout << "listener() for " << this << ", got: " <<
    				i << ", " << l << ", " << d << endl;
    		}
    	};
    
    	MyClassWithMethod instance1;
    	MyClassWithMethod instance2;
    	instance1.registerCB(d2);
    	instance2.registerCB(d2);
    	d2.broadcast(65000, 12345678910, 3.14159265);
    	d2.broadcast(56000, 1987654321, 14159265.3);
    }
    


  • Der Code aus dem Artikel ja. Hat doch keiner was gegenteiliges behauptet.
    th69 hat gemeint bei ihm hat sein Beispiel nicht kompiliert und bei mir mein "richtiges" Projekt nicht.



  • Naja, anderen Code hast Du ja noch immer nicht gezeigt.

    @It0101 sagte in c++ 11 Event implementation:

    Hast du mal versucht, deinen Originalcode zu nehmen, die relevanten Teile rauszuschneiden und die Reste soweit zu reduzieren, solange der Fehler noch da ist? Funktionen und Objekte kann man ja dann zur Veröffentlichung auch umbenennen, um die tatsächliche Funktionalität zu verschleiern. Das ist natürlich für dich etwas Aufwand, aber wenn du der Sache auf die Spur kommen willst, wird dir vermutlich nicht viel anderes übrig bleiben.

    DAS. Sonst ist und bleibt das ein sinnloses Ratespiel.



  • Jetzt weiß ich auch meinen Fehler: using namespace std::placeholders; (programmiere jetzt meistens C#...).

    Nun läuft es auch ohne Dereferenzierung: geänderter Ideone-Code





  • Ja swordfish, wie oft soll ich es denn noch sagen? Ist doch klar.
    Es soll kein Ratespiel werden. Um das richtige Projekz geht es doch nicht mehr.
    Hier tut es ja jetzt. Vieleicht auch mit Derferenzierung. Habe ich nun nicht mehr getestet.

    Mir war nicht klar wieso es mit und ohne Dereferenzierung funktioniert. Und das war meine letze Frage.
    Und da kam dann hustbear daher und hat mich nochmals auf den fehlenden Sourcecode hingewiesen und du nochmals auf den Beitrag. Und darauf habe ich lediglich geantwortet ohne Anspruch auf Hilfe zu dem fehlenden Code.



  • Na dann ist ja gut.



  • Ja es ist gut. Ausser natürlich die Frage wieso geht es mit und ohne dereferenzierung.



  • @booster sagte in c++ 11 Event implementation:

    Ausser natürlich die Frage wieso geht es mit und ohne dereferenzierung.

    Weil es std::bind bei einer Member Function sch*** egal ist, was es bekommt, eine Referenz oder einen Pointer. Es verhält sich in beiden Fällen exakt gleich.

    #include <functional>
    #include <iostream>
    
    struct foo
    {
    	static int count;
    	int id;
    	foo() : id{ ++count } {}
    
    	void bar(int arg){ std::cout << static_cast<void*>(this) << "->" << "bar(" << arg << ") (id = " << id << ")\n"; }
    };
    
    int foo::count{};
    
    int main()
    {
    	using namespace std::placeholders;
    
    	foo a;
    	foo b;
    
    	auto f0{ std::bind(&foo::bar, a, _1) };
    	auto f1{ std::bind(&foo::bar, std::ref(a), _1) };
    	auto f2{ std::bind(&foo::bar, &b, _1) };
    
    	f1(0);
    	f1(1);
    	f2(2);
    }
    

Anmelden zum Antworten