Migliorare questo uno per uno. Per evitare ambiguità, userò nomi diversi template argomento nell'esempio
template<class C, class signature> void f(signature C::*ptr) {}
Tutte le citazioni si riferiscono all'ultima bozza di lavoro dello standard C++ 14.
Per prima cosa dobbiamo capire come vengono trattati i parametri del modello.
[temp.param]/3 Un tipo-parametro il cui identificatore non segue i puntini di sospensione definisce suo identificatore di essere un nome-typedef
Quindi la tua definizione di modello ha due parametri T
e la firma. Quando si utilizza signature
nel corpo del modello, è quindi equivalente alla typedef
typedef void signature(float, int);
Questo typedef può essere utilizzato per dichiarare un parametro di puntatore a funzione, come nel tuo esempio:
[dcl.fct ]/12 un typedef di tipo funzione può essere utilizzata per dichiarare una funzione, ma è non essere usato per definire una funzione
Nei parametri del Te Funzione mplate, si scrive signature T::*ptr
, vediamo cosa dice la norma sulla puntatori membri:
[dcl.mptr]/1 In una dichiarazione in cui T D
D
ha la forma
nested-name-specifier * attribute-specifier-seq_opt cv-qualifier-seq_opt D1
e la identificatore nome nidificato indica una classe e il tipo dell'identificatore nella dichiarazione T D1
è derivato-elenco-tipo-dichiaratore T, quindi il tipo di identificatore di D
è derivato-dichiaratore-tipo-elenco cv-qualificatore-seq puntatore a membro della classe nested-nome-specificatore di tipo T.
Nel nostro esempio, è T
signature
, la funzione typedef, e D
è C::*ptr
.
Questo spiega quali tipi il compilatore dedurre per l'esempio
void f(void(A::*ptr)(float, int));
@ Daniel Frey sì. So che tutto funziona. Chiedo: perché funziona? Dove posso leggere nello standart C++ che tale cosa è corretta. –