2012-06-19 9 views
12

Considere esta función plantilla:Deducir argumento de plantilla de std :: función de llamada de la firma

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

¿Por qué no es posible que el compilador para deducir ReturnT de la firma llamada pasado?

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

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

Una respuesta a [una de mis preguntas anteriores] (http://stackoverflow.com/questions/9625526/check-at-compile-time-if-template-argument-is-void) permite este tipo de sintaxis. Espero que eso ayude. Está especializado en caso de que el tipo de devolución también sea nulo. – chris

+0

@chris Gracias por la pista, intentaré entenderlo :) –

+0

N.B. muy similar a http://stackoverflow.com/q/7608741/981959 y http://stackoverflow.com/q/9242234/981959, pero creo que las respuestas aquí son más claras para esta pregunta específica. –

Respuesta

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

foo(bar); // works just fine 

C++ no puede deducir el tipo de retorno de su función bar porque tendría que saber el tipo antes de que pudiera encontrar todos los constructores que toman el puntero de su función.

Por ejemplo, ¿quién dice que std::function<std::string()> no tiene un constructor tomando bool (*)()?

0

La función bar es de tipo bool (*)() o así, es decir: una normal de pre-C++ tipo 11 función. No estoy tan seguro de C++ 11, pero creo que el compilador no ve la conexión entre bool (*)() y const std::function<ReturnT()>&, incluso cuando la primera se puede convertir implícitamente en la segunda para ReturnT = bool.

+0

¿Cómo se puede convertir un puntero a un tipo de función? –

+0

En realidad, no importa cómo proceda la conversión, la definición de std :: function es: 'template class function ' donde 'R' se conoce como' bool' ... por lo tanto ' ReturnT' debe ser deducible para 'foo', ¿verdad? –

+0

@Karl, pero 'std :: function' tiene un constructor que toma _any_type, por lo que' bool (*)() 'también se puede convertir a' std :: function 'u otros tipos; no hay ninguno, secuencia de conversión única que significa que solo se puede deducir una única especialización de 'std :: function' –

13

Un puntero de función de tipo bool (*)() se puede convertir a std::function<bool()> pero no es del mismo tipo, por lo que es necesaria una conversión. Antes de que el compilador pueda verificar si esa conversión es posible, necesita deducir ReturnT como bool, pero para hacer eso necesita saber que std::function<bool()> es una posible conversión, que no es posible hasta que deduzca ReturnT ... vea el problema?

Además, tenga en cuenta que bool(*)() también se puede convertir a std::function<void()> o std::function<int()> ... ¿Qué se debe deducir?

considerar esta simplificación:

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

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

int main() 
{ 
    foo(1); 
} 

¿Cómo se puede saber si el compilador desea crear function<int> o function<char> o function<void> cuando todos ellos pueden ser construidos de una forma int?

Cuestiones relacionadas