2012-06-19 2 views
12

Consideriamo questa funzione template:Dedurre modello argomento da std :: funzione di chiamata firma

template<typename ReturnT> 
ReturnT foo(const std::function<ReturnT()>& fun) 
{ 
    return fun(); 
} 

Perché non è possibile per il compilatore di dedurre ReturnT dalla firma chiamata passato?

bool bar() { /* ... */ } 

foo<bool>(bar); // works 
foo(bar); // error: no matching function call 
+1

Una risposta a [una delle mie precedenti domande] (http://stackoverflow.com/questions/9625526/check-at-compile-time-if-template-argument-is-void) consente questo tipo di sintassi. Spero che aiuti. È specializzato nel caso in cui anche il tipo di reso sia nullo. – chris

+0

@chris Grazie per il suggerimento - proverò a capirlo :) –

+0

N.B. molto simile a http://stackoverflow.com/q/7608741/981959 e http://stackoverflow.com/q/9242234/981959, ma penso che le risposte qui siano più chiare per questa specifica domanda. –

risposta

7
std::function<bool()> bar; 

foo(bar); // works just fine 

C++ non può dedurre il tipo restituito dalla funzione bar perché avrebbe dovuto conoscere il tipo prima che potesse trovare tutti i costruttori che tolgono il puntatore a funzione.

Ad esempio, chi può dire che std::function<std::string()> non ha un costruttore che prende un bool (*)()?

0

La funzione bar è di tipo bool (*)() o così, che è: un normale pre-C++ tipo 11 funzione. Non sono così sicuro di C++ 11, ma suppongo che il compilatore non veda la connessione tra bool (*)() e const std::function<ReturnT()>&, anche quando il primo può essere convertito implicitamente nel secondo per ReturnT = bool.

+0

Come può essere convertito un puntatore a funzione in un tipo di funzione? –

+0

In realtà, indipendentemente da come procede la conversione, la definizione di std :: function è: 'template function class ' dove 'R' è noto come' bool' ... quindi ' ReturnT' dovrebbe essere deducibile per 'pippo', giusto? –

+0

@Karl, ma 'std :: function' ha un costruttore che prende _any_ type, quindi' bool (*)() 'potrebbe anche essere convertito in' std :: function 'o altri tipi - non c'è un singolo, sequenza di conversione unica che significa solo una singola specializzazione 'std :: function' può essere dedotta –

13

Un puntatore funzione del tipo bool (*)() può essere convertito std::function<bool()> ma non è lo stesso tipo, quindi è necessaria una conversione. Prima che il compilatore possa verificare se è possibile effettuare tale conversione, è necessario dedurre , ma per farlo è necessario sapere già che std::function<bool()> è una possibile conversione, che non è possibile finché non si deduce ReturnT ... vedere il problema?

Inoltre, si consideri che bool(*)() potrebbe anche essere convertito in std::function<void()> o std::function<int()> ... quale dovrebbe essere dedotto?

Considerate questa semplificazione:

template<typename T> 
    struct function 
    { 
    template<typename U> 
     function(U) { } 
    }; 

template<typename T> 
    void foo(function<T>) 
    { } 

int main() 
{ 
    foo(1); 
} 

Come può il compilatore sapere se si voleva creare function<int> o function<char> o function<void> quando tutti possono essere costruiti sotto forma di un int?