2012-06-03 35 views
15

W poniższym przykładowym kodzie wywołanie foo działa, gdy połączenie z bar kończy się niepowodzeniem.Przekazanie funkcji jako jawnego parametru szablonu

Jeśli skomentuję połączenie z bar, kod zostanie skompilowany, co oznacza, że ​​sama definicja jest w porządku. Jak zatem poprawnie wywołać 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

Zobacz także [Funkcja przekazana jako argument szablonu] (https://stackoverflow.com/q/1174169/608639). – jww

Odpowiedz

26

tu ma problemu, multiply nie jest typ; jest to wartość o wartości, ale szablon funkcji bar oczekuje, że argumentem szablonu będzie typ. Stąd błąd.

Jeśli zdefiniować szablon funkcji jak:

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

to będzie działać. Zobacz demo online: http://ideone.com/qJrAe

Można uprościć składnię przy użyciu typedef jak:

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

Dziękujemy za jasne wyjaśnienie! – tajmahal

7

multiply nie jest typem, to funkcja. W tym kontekście rozpada się na wskaźnik funkcji. Jednak bar jest szablonem dla typu, który ponownie nie jest multiply.

Nawaz już odpowiedział na pytanie na odwrót (jak zmienić definicję bar być używany z funkcji), ale aby odpowiedzieć na wyraźne pytanie, jak zadzwonić bar jak masz to, czego potrzeba odpowiedniego typu, tak:

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

Jeśli ma zamiar tego użyć, musi również zmienić 'bar'. Składnia 'F (x, y)' powinna mieć postać 'F (x, y)()'. – Nawaz

+0

@Nawaz Nie, 'Type' w rzeczywistości nie jest funktorem. Jest to tylko typ z odpowiednim konstruktorem i przeciążeniem wyjścia strumienia (w tym przypadku odpowiedni operator konwersji, który ma przeciążenie wyjścia strumienia). (patrz http://ideone.com/AgQGc) –

+0

Ohh ... Przeoczyłem to ... być może dlatego, że funktor byłby tu lepszą alternatywą, dlatego oczekiwałem tego. – Nawaz

Powiązane problemy