2012-05-15 9 views
5

Ich habe gerade selbst eine Klasse erstellenerfinde ich das Rad mit dieser trivialen Methode Call Forwarding Klasse neu?

template <typename T> struct invoker { 
    void operator()(T& it) const {it();} 
}; 

so konnte ich ein invoker<foo> etwas passieren (was nicht unter meiner Kontrolle ist), die invoker<foo>::operator()(foo&) darauf mit verschiedenen foo Instanzen immer wieder anrufen will, es zu erhalten, Weiterleiten Sie diese Anrufe an die foo::operator()() Methode.

Ich weiß, es sind nur ein paar Zeilen, aber das scheint so etwas zu sein, was wahrscheinlich schon von STLs funktionalem oder boost::bind irgendwie vorgesehen ist. Außer ich kann den Trick nicht sehen, wenn es einen gibt. (Ich bin sicher, ich bin nicht die erste Person, etwas zu verwenden, sehr wie diese, es einen Namen hat?)

+1

ich denke C++ 11 hat auch etwas dafür – pyCthon

+1

Für jetzt bin ich auf g ++ 4.4.5; Ich glaube nicht, dass g ++ bis 4.5 lambdas hat. Neugierig, eine Lambda-Lösung zu sehen, wenn man sie trotzdem veröffentlicht; Ich kann mit meiner Invoker-Klasse bis zu einem g ++ Versions-Upgrade leben. – timday

+0

Warum würden Sie 'foo :: operator()' nicht direkt aufrufen? Ich meine, die Klasse, die 'invoker :: operator()' aufruft, muss etwas wie 'some_invoker (some_foo);' tun, während man es einfach so nennen könnte: 'some_foo();'. Sie fügen eine unnötige indirekte Ebene hinzu. – mfontanini

Antwort

5

Ja, Sie erfinden das Rad neu. std :: mem_fun_ref macht was Sie wollen.

std::vector<foo> foos; 

... 

std::for_each(foos.begin(), foos.end(), std::mem_fun_ref(&foo::operator())); 

Alternativ:

std::vector<foo*> foos; 

... 

std::for_each(foos.begin(), foos.end(), std::mem_fun(&foo::operator())); 

nicht mit zu verwirren zu müssen, ob Ihre param ist ptr oder nicht, ist ein großer Vorteil von boost :: mem_fn.

Alles viel komplexer als das und Sie beginnen in Schwierigkeiten mit den C++ 03 Bindemitteln zu laufen und brauchen etwas ausdrucksvolleres wie boost.bind.

+4

Ich wollte nur darauf hinweisen, dass "std :: mem_fun" und "std :: mem_fun_ref" in C++ 11 für "std :: mem_fn" veraltet sind. –

6

Nun können Sie std::bind verwenden, wahrscheinlich boost::bind auch das gleiche Verhalten zu erreichen:

#include <string> 
#include <iostream> 
#include <functional> 

struct foo { 
    void operator()() { 
     std::cout << "Hallo, im at addr: " << std::hex << this << std::endl; 
    } 
}; 

int main() { 
    std::function<void(foo*)> fun = std::bind(&foo::operator(), std::placeholders::_1); 
    foo f1, f2; 
    fun(&f1); 
    fun(&f2); 
} 

Ausgänge:

Hallo, im at addr: 0xbffc396a 
Hallo, im at addr: 0xbffc3969 

Wenn Sie eine Template-Klasse für das Argument Typ verwenden, können Sie die gleiche behvaiour haben, ohne das Rad neu zu erfinden.

bearbeiten: wie verrückt Eddie darauf hingewiesen, können Sie einfach boost::mem_fn oder std::mem_fn verwenden:

std::function<void(foo*)> fun = std::mem_fn(&foo::operator()); 

Statt bind.

+1

Sie brauchen hier eigentlich keine Bindung und es kann sich lohnen, sie wegzulassen. Bind muss ein Argumentumwandlungssystem durchlaufen, um die beiden Argumentlisten zusammenzuführen und die Zielaufruffunktion aufzurufen. boost :: mem_fn macht den Trick und tatsächlich bind() für Memberpointer verwendet es. –

+0

@CrazyEddie netter, ich habe 'mem_fn' vor einiger Zeit benutzt, aber total vergessen. Edited meine Antwort: D – mfontanini

+0

OK, das ist genau die Art von was ich suchte, danke; es ist offensichtlich, wenn man es sieht, biss ich mich irgendwie (zu spät) davon überzeugt hatte, dass, weil die foo-Methode, an der ich interessiert war, keine Argumente hatte, es keine Rolle für einen _1 Platzhalter gab ... so falsch. – timday