2014-12-22 20 views
11

In C++ 11 è possibile creare un'istanza std :: funzione come questa:C++ std :: funzione simile

std::function<void(int)> f1; 
std::function<int(std::string, std::string)> f2; 
//and so on 

Ma mentre v'è abbondanza di informazioni sui modelli variadic sul web, non riesco per trovare qualsiasi articolo su come scrivere std :: template simile alla funzione che accetta gli argomenti tra parentesi. Qualcuno potrebbe spiegare la sintassi e le sue limitazioni o almeno indicare una spiegazione esistente?

risposta

14

Non c'è niente di speciale, è un tipo di funzione ordinario. Quando si dichiara una funzione come questa:

int foo(char a, double b) 

Poi il suo tipo è int (char, double). Un modo per "scartare" i singoli tipi di argomenti e il tipo di ritorno è usare la specializzazione del modello parziale. In sostanza, std::function sembra qualcosa di simile:

template <class T> 
struct function; // not defined 

template <class R, class... A> 
struct function<R (A...)> 
{ 
    // definition here 
}; 
+0

Quindi, se ho capito bene, int (char, double) viene interpretato come un singolo tipo di funzione, ma possiamo quindi estrarre il tipo di ritorno e l'elenco dei parametri con specializzazione parziale? – Smiles

+0

@Cynic Sì, è esattamente come funziona. Ho modificato la risposta di conseguenza. – Angew

+0

Ho bisogno di sintassi come 'modello void foo (F (int) intCallable) {...}':/ – jaskmar

3

Praticamente come qualsiasi altro modello, dal momento che int(std::string, std::string) è solo un tipo.

Ecco un esempio davvero ingenua che compila:

template <typename FType> 
struct Functor 
{ 
    Functor(FType* fptr) : fptr(fptr) {} 

    template <typename ...Args> 
    void call(Args... args) 
    { 
     fptr(args...); 
    } 

private: 
    FType* fptr; 
}; 

void foo(int x, char y, bool z) {} 

int main() 
{ 
    Functor<void(int, char, bool)> f(&foo); 
    f.call(1, 'a', true); 
    //f.call(); // error: too few arguments to function 
} 

In realtà si avrebbe una specializzazione sul FType essere ReturnType(ArgTypes...), anche se il mio esempio ingenuo sarà già vi darà la convalida è necessario se si tenta di invocarlo in modi compatibili.

Problemi correlati