2016-03-31 6 views
1

Ist es in C++ möglich, eine Funktion mit seinen Parametern als Argument übergeben? Ich möchte den Funktionsnamen nicht einfach weitergeben. Ich möchte den Funktionsnamen mit den enthaltenen Parametern übergeben. Beachten Sie, dass ich nicht weiß, wie viele Parameter die Funktion empfängt oder die Typen. Deshalb füge ich sie nicht als zusätzliche Parameter hinzu. Ich möchte nur einen Verweis auf einen Funktionsaufruf, den ich bei Bedarf ausführen kann. Zum Beispiel:Übergeben Sie eine Funktion mit den Argumenten in C++

CallFunction(f(param1, param2)); 

Aber f nicht ausgewertet wird, bekomme ich nur einen Verweis auf die Anruffunktion und ich kann es bewerten, wenn ich will, zum Beispiel:

CallFunction(f){ 
//do something and then in one moment do: 
f; // and this calls f(param1, param2) 
} 

Jede Art und Weise, in dem diese in C++ erreicht werden? Vielen Dank im Voraus.

+4

[std :: bind] (http://en.cppreference.com/w/cpp/utility/functional/bind). – songyuanyao

+0

@ songyuanyao ist es möglich, dann die Information des Anrufs als eine Zeichenfolge, z. Die bañe der Funktion, die aufgerufen wird? –

+0

Sorry, was ist 'bañe'? – songyuanyao

Antwort

0
  1. Accept jede aufrufbare Funktion als erstes Argument
  2. Verwenden variadische Vorlagen und eine beliebige Anzahl von Argumenten jeder Art akzeptieren.
  3. Verwenden Sie die perfekte Weiterleitung.

http://ideone.com/z2kLUx

int HelloWorld(string var1, const char* var2) 
{ 
    cout << var1 << " " << var2 << endl; 
    return 5; 
} 

template<typename Fn, typename... Args> 
auto CallFunction(Fn fn, Args&&... args) 
{ 
    return fn(forward<Args>(args)...); 
} 

int main() 
{ 
    cout << "Value returned: " << CallFunction(HelloWorld,"Hello","World"); 
    return 0; 
} 

Dies ist die einfache Version, die einen Nachteil hat: Sie eine Funktion angeben, die nicht-void zurückgibt, aber dies leicht behoben werden kann. Die einfache Lösung ist das Erstellen einer anderen CallFunction, die void mit einem anderen Namen zurückgibt oder std::enable_if verwendet.

http://ideone.com/El3WUi

template<typename Fn, typename... Args> 
auto CallFunction(Fn fn, Args&&... args) -> typename enable_if<is_same<void, decay_t<decltype(fn(forward<Args>(args)...))>>::value, decltype(fn(forward<Args>(args)...))>::type 
{ 
    fn(forward<Args>(args)...); 
} 

template<typename Fn, typename... Args> 
auto CallFunction(Fn fn, Args&&... args) -> typename enable_if<!is_same<void, decay_t<decltype(fn(forward<Args>(args)...))>>::value, decltype(fn(forward<Args>(args)...))>::type 
{ 
    return fn(forward<Args>(args)...); 
} 
3

Ein komplettes Beispiel von std::bind mit:

#include <iostream> 
#include <functional> 

void f(int p1, int p2) { 
    std::cout << "In f(" << p1 << "," << p2 << ")\n"; 
} 

template <typename F> 
void CallFunction(F f) 
{ 
    std::cout << "Start CallFunction\n"; 
    f(); 
    std::cout << "End CallFunction\n"; 
} 

int main() 
{ 
    CallFunction(std::bind(f, 2, 3)); 
} 
0

Sie haben mehrere Möglichkeiten.

Eine besteht darin, einen Wrapper-Abschluss zu erstellen, der den Aufruf Ihrer Funktion kapselt. Dies hat den Vorteil, dass Sie bei Bedarf die Ausgabe Ihrer Funktion transformieren können.

Das Ausführen eines einfachen Wrappers ist identisch mit dem Verwenden des std::bind, wie andere bereits erwähnt haben.

#include <functional> 
#include <iostream> 

void CallFunction(std::function<void(void)> f) { 
    f(); 
} 

int main() { 
    auto closure = [](int a, int b) { 
     std::cout << a << ", " << b << std::endl; 
    }; 

    auto wrapper = [closure]() { 
     closure(1, 2); 
    }; 

    CallFunction(wrapper); 

    CallFunction(std::bind(closure, 3, 4)); 

    return 0; 
} 
Verwandte Themen