2016-04-07 9 views
3

Ich habe versucht, eine Karte zu Klassenmethoden mit C++ 11 function zu machen.Zuordnung zur Methode C++ 11

Die C-Style Funktionszeiger:
Methode:

void MyClass::MyMethod(void*); 

Karte declare:

std::map<int, void (MyClass::*)(void*)> mapIdToMethod; 

Karte einfügen:

mapIdToMethod.insert(std::make_pair(2, &MyClass::MyMethod)); 

Methodenaufruf:

Der obige Code ist funktioniert, aber wie kann ich es umwandeln, um C++ 11 function zu verwenden?
Was ich versucht habe:
Karte declare:

std::map<int, function<void(void*)>> mapIdToMethod;//The map declare 

Nun, wie kann ich einfügen und das Verfahren an diesem map nennen?

+6

wenn es keine Probleme mit dem Code, wie Sie es haben, es dabei belassen. ** Wenn es nicht kaputt ist, repariere es nicht ** – bolov

+4

std :: function ist eine andere Sache. Ihr ursprünglicher Code speichert nur die Mitgliedsfunktionszeiger. std :: function würde erfordern, dass der Elementfunktionszeiger an eine Instanz der Klasse gebunden war. –

+3

Wenn die Funktion MyMethod einen internen Status verwendet, müssen Sie wahrscheinlich [bind] (http://en.cppreference.com/w/cpp/utility/functional/bind) oder Lambda verwenden. Aber wie @bolov sagte, sollten Sie es nicht ändern, wenn es funktioniert. Zumindest, weil std :: function den Runtime-Overhead darauf legt, also lass es einfach. – Incomputable

Antwort

2

Ich bin auch ein Fan von function über C-Stil Zeiger, aber es ist wichtig, dass Sie erkennen, dass die analoge für void (MyClass::*)(void*) sind function<void(MyClass&, void*)>nichtfunction<void(void*)>. So könnten Sie replizieren, was Sie bereits in MapIdToMethod mit haben gehen habe:

map<int, function<void(MyClass&, void*)>> bar; 

Sie dazu die gleiche Art und Weise einfügen könnte, wie Sie MapIdToMethod eingefügt (bar.insert(make_pair(2, &MyClass::MyMethod)), aber auch mem_fn verwenden könnte, die nicht wollten,

bar.insert(make_pair(2, mem_fn(&MyClass::MyMethod))); 

Nun, um Ihre Frage zu beantworten: möglich gewesen, wenn sie MapIdToMethod Einfügen zu verwenden. Gegeben:

map<int, function<void(void*)>> foo; 

Sie können Elementfunktionen einsetzen, die eine void* nehmen und nichts zurückgeben, aber nur, wenn Sie bereits das Objekt, auf dem Sie die Anrufe aufgebaut machen wollen. Sie können das bind mit tun:

MyClass mc; 

foo.insert(make_pair(2, bind(&MyClass::MyMethod, mc, placeholders::_1))); 

Live Example

+0

Hallo, Danke! – Evyatar

4

Wahrscheinlich nicht so effizient wie das Original, aber vielleicht leichter zu lesen:

std::map<int, std::function<void (MyClass&,void*)>> mapIdToMethod;  
mapIdToMethod.emplace(2, [](MyClass& c,void* p){ c.MyMethod(p);}); 
// alternatively: 
using std::placeholders::_1;  
using std::placeholders::_2; 
mapIdToMethod.emplace(2,std::bind(&MyClass::MyMethod,_1,_2)); 

MyClass mc; 
mapIdToMethod.at(2)(mc, nullptr); 
+0

Nein, es ist nicht einfacher zu lesen. Definitiv coole Verwendung von C++ 11-Funktionen, aber überhaupt nicht leicht zu lesen. – StoryTeller

+1

Da OP C++ 11 hat, könnten Sie 'std :: bind' und' std :: placeholders :: _ 1' verwenden. – juanchopanza

+0

@juanchopanza: Ich stimme zu. – MarkusParker