2015-04-28 14 views
10

Vorrei implementare un chiamante funzione che funziona proprio come il costruttore thread. Ad esempioC++ chiamante funzione universale

std::thread second (bar,0); 

inizierà un thread che chiama bar con l'unico argomento 0. Mi piacerebbe fare la stessa cosa, ma non so come.

Ad esempio, dato:

void myFunc(int a){ 
    cout << a << endl; 
} 

Vorrei:

int main() { 
    caller(myFunc,12); 
} 

per chiamare myFunc con il parametro 12.

+6

'std :: function' e' std :: bind'? –

+0

considera segnale/slot? – user3528438

+1

Per C++ 17, ci sarà ['std :: invoke()'] (http://en.cppreference.com/w/cpp/utility/functional/invoke), che fa esattamente questo. – DanielKO

risposta

21

std::bind renderà un oggetto chiamabile da qualsiasi oggetto chiamabile con un insieme arbitrario di parametri, proprio come fa il costruttore thread. Quindi, solo avvolgere che in una funzione che lo chiama:

template <typename... Args> 
auto caller(Args &&... args) { 
    return std::bind(std::forward<Args>(args)...)(); 
} 

Si noti che il tipo di ritorno auto richiede C++ 14 o successivo. Per C++ 11, è necessario restituire void o specificare il tipo:

auto caller(Args &&... args) 
    -> decltype(std::bind(std::forward<Args>(args)...)()) 
+0

posso chiamare un metodo da un oggetto con questo? –

+2

@MaxianNicu: Sì. Per la funzione membro 'Class :: method()' e un oggetto 'object', chiamala con' caller (& Class :: method, & object) '. –

+0

Grande. Ha funzionato. Grazie. –

7

Se tutto quello che vogliamo fare è chiamare una funzione arbitraria con un argomento arbitrario, questo è solo un modello su entrambi i tipi:

template <typename Function, typename Arg> 
void call_with_one(Function&& f, Arg&& arg) { 
    f(std::forward<Arg>(arg)); 
} 

che è possibile espandere per chiamare con qualsiasi numero di argomenti, rendendo variadic :

template <typename Function, typename... Arg> 
void call_with_any(Function f, Arg&&... args) { 
    f(std::forward<Arg>(args)...); 
} 

o realmente f dovrebbe essere un punto di riferimento di inoltro così:

template <typename Function, typename... Arg> 
void call_with_any(Function&& f, Arg&&... args) { 
    std::forward<Function>(f)(std::forward<Arg>(args)...); 
} 

Si noti che questo funzionerà solo con funzioni e oggetti che implementano operator(). Se f è un puntatore a membro, ciò non riuscirà: sarà invece necessario utilizzare std::bind come suggerisce Mike Seymour.

+0

Suggerisco di prendere 'f' tramite il riferimento di inoltro. – Quentin

+2

Per funzionare "proprio come il costruttore' thread' ", deve funzionare anche se' f' è un puntatore a funzione membro. –

+0

@MikeSeymour Preferirei collegare alla tua risposta piuttosto che copiarla :) – Barry

Problemi correlati