2015-05-09 8 views
5

Il codice seguente funziona correttamente ma non riesco a capire in base a quali punti dello standard C++ dovrebbe essere valido.Modelli C++ con puntatore alla funzione membro per firma e tipo

template< class C, class signature > 
void f(signature C::*ptr) { } 

Quando C = A e signature = void(float, int), la funzione f sarà

void f(void(A::*ptr)(float, int)) 

Sulla base di quali parti della norma, fa il modello si applicano a questi ultimi?

+0

@ Daniel Frey sì. So che tutto funziona. Chiedo: perché funziona? Dove posso leggere nello standart C++ che tale cosa è corretta. –

risposta

4

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 DD 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, è Tsignature, la funzione typedef, e D è C::*ptr.

Questo spiega quali tipi il compilatore dedurre per l'esempio

void f(void(A::*ptr)(float, int)); 
Problemi correlati