C ++ detrazione del “puntatore non il tipo di funzione” parametri del modello di classe
Domanda
Si consideri una classe template come:
template<typename ReturnType, ReturnType Fn()>
class Proxy
{
void run()
{
ReturnType ret = Fn();
// ... do something ...
}
};
// and a functions
int fn1() { return 5; }
float fn2() { return 5; }
Questo può essere un'istanza utilizzando:
Proxy<int, &fn1> p1;
Ma dichiarando esplicitamente il tipo di valore di ritorno sembra inutile. Quello che sto cercando di realizzare è qualcosa di simile:
someProxyInstantation<&fn1> p1;
someProxyInstantation<&fn2> p2;
Purtroppo, io non sono un C ++ aspettarsi e questo mi sembra un angolo nascosto del linguaggio (almeno per me).
Se solo potessi ottenere dal puntatore alla funzione al suo tipo - qualcosa di simile a: std :: tr1 :: result_of <& Fn> :: tipo // Errore 1 Errore C2923: 'std :: tr1 :: result_of': 'fn1' non è un tipo di modello argomento valido per il parametro '_Fty'
l'errore ha un senso in quanto il parametro non è un "tipo" a tutti
C ++ 0x ha il decltype (& fn1), ma che è lontano anni.
Qualsiasi modo di fare questo in C ++ 03 (+ TR1)?
Restrizioni: -. Non voglio passare il funtore, F1 e F2 deve rimanere funzioni globali che hanno un valore di ritorno (non può spostarlo parametro))
Soluzione
Questo non è possibile in C ++ 03. Se si desidera passare un puntatore a funzione come un parametro non tipo, il compilatore deve conoscere il tipo di parametro. Quindi, è necessario fornire i pezzi mancanti (in questo caso, il tipo di ritorno). Si può dare il proxy il puntatore a funzione come un valore in fase di esecuzione, e fornire con il tipo di esso come unico argomento. Poi si potrebbe scrivere una funzione generatore per te che fa questo lavoro:
template<typename T>
Proxy<T> make_proxy(T t) { return Proxy<T>(t); }
Purtroppo, in corrente C ++, si devono ancora dare il tipo al fine di assegnare a una variabile automatica:
Proxy<int(*)()> p = make_proxy(&fn1);
Non è possibile utilizzare ancora auto p = make_proxy(&fn1);
. Si noti che se si desidera utilizzare un tipo di funzione sul lato sinistro, è necessario modificare la funzione del generatore di fornire non un tipo di puntatore a funzione:
template<typename T>
Proxy<typename boost::remove_pointer<T>::type> make_proxy(T t) {
return Proxy<typename boost::remove_pointer<T>::type>(t);
}
Ora si può fare
Proxy<int()> p = make_proxy(&fn1);
con il proxy, è ora possibile solo fare
doSomething(make_proxy(&fn1));
E se doSomething è basato su modelli o altrimenti polimorfa, non richiedono di conoscere l'esatto tipo di funzione.