2012-06-03 29 views
15

En el siguiente ejemplo de código, la llamada al foo falla, mientras que la llamada al bar falla.Pasar una función como un parámetro de plantilla explícita

Si comento la llamada a bar, el código se compila, lo que me dice que la definición de bar está bien. Entonces, ¿cómo se llamaría correctamente al bar?

#include <iostream> 

using namespace std; 

int multiply(int x, int y) 
{ 
    return x * y; 
} 

template <class F> 
void foo(int x, int y, F f) 
{ 
    cout << f(x, y) << endl; 
} 

template <class F> 
void bar(int x, int y) 
{ 
    cout << F(x, y) << endl; 
} 

int main() 
{ 
    foo(3, 4, multiply); // works 
    bar<multiply>(3, 4); // fails 

    return 0; 
} 
+0

Ver también [Función pasada como argumento de plantilla] (https://stackoverflow.com/q/1174169/608639). – jww

Respuesta

26

El problema aquí es, multiply no es un tipo ; es un valor pero la plantilla de función bar espera que el argumento de la plantilla sea tipo. De ahí el error.

Si se define la plantilla de función como:

template <int (*F)(int,int)> //now it'll accept multiply (i.e value) 
void bar(int x, int y) 
{ 
    cout << F(x, y) << endl; 
} 

entonces todo funcionará bien. Ver demostración en línea: http://ideone.com/qJrAe

puede simplificar la sintaxis usando typedef como:

typedef int (*Fun)(int,int); 

template <Fun F> //now it'll accept multiply (i.e value) 
void bar(int x, int y) 
{ 
    cout << F(x, y) << endl; 
} 
+2

¡Gracias por la clara explicación! – tajmahal

7

multiply no es un tipo, es una función. En ese contexto, se descompone en un puntero de función. Sin embargo, bar está modelado para un tipo que, nuevamente, multiply no lo es.

Nawaz ya respondió a la pregunta a la inversa (cómo cambiar la definición de bar a ser utilizados por funciones), pero para responder a su pregunta explícita de cómo llamar a bar como lo tienes, es necesario un tipo adecuado, como este:

struct Type { 
    const int result; 
    Type(int x, int y): result(x * y) {} 
    operator int() const { return result; } 
}; 

// usage 
bar<Type>(x, y); 

// (edit) a suitable type doesn't necessarily mean a new type; this works as well 
// if you aren't trying to solve any specific problem 
bar<std::string>(64, 64); 
+0

Si él va a usar esto, entonces él necesita cambiar 'bar' también. La sintaxis 'F (x, y)' debería convertirse en 'F (x, y)()'. – Nawaz

+0

@Nawaz No, 'Type' no es realmente un funtor. Es solo un tipo con un constructor adecuado y una sobrecarga de salida de flujo (en este caso, un operador de conversión adecuado que ya tiene una sobrecarga de salida de flujo). (ver http://ideone.com/AgQGc) –

+0

Ohh ... Pasé por alto eso ... posiblemente porque un functor sería una mejor alternativa aquí, por lo tanto, estaba esperando eso. – Nawaz

Cuestiones relacionadas