2016-05-17 20 views
6

Compilando su C++ 03, ho tentato di scrivere una funzione template di test che restituisce una funzione pointer-to-member di una funzione membro che restituisce int , e prende due argomenti float:Restituire la funzione pointer-to-member (senza typedefs)

template<typename TemplateClass> 
int (TemplateClass::*)(float,float) Testtest(TemplateClass &A) 
{ 
    return &TemplateClass::Function; 
} 

Ma, naturalmente, non importa ciò che le variazioni sulla sintassi puntatore-a-membro funzione che uso, il compilatore si lamenta di errori di inizializzazione. Typedef, sebbene funzioni con classi conosciute, per ovvi motivi (conflitti di denominazione), non accetta gli argomenti della classe template per le classi che non posso sapere in anticipo e che probabilmente useranno la stessa funzione.

Che modo non tipografico esiste per ottenere questa funzione per compilare e restituire una funzione puntatore-membro?

risposta

5

di dichiararla senza un tipo alias, senza detrazione tipo, e senza un tipo di ritorno finale:

template<typename TemplateClass> 
int (TemplateClass::* Testtest(TemplateClass &A))(float,float) 

Ma naturalmente questo non è ciò che si userebbe nel codice reale. Invece si dovrebbe usare un alias template:

template<typename T> 
using return_type = int (T::*)(float,float); 

template<typename TemplateClass> 
return_type<TemplateClass> Testtest(TemplateClass &A) 

Oppure torna tipo deduzione in C++ 14:

template<typename TemplateClass> 
auto Testtest(TemplateClass &A) 

O un tipo di ritorno finale (in C++ 11):

template<typename TemplateClass> 
auto Testtest(TemplateClass &A) -> int (TemplateClass::*)(float,float) 
+0

Beh, non avrei mai immaginato il primo. È così ... contorto. C++, perché lo fai ?! – c1646091

+1

@ c1646091 Quella sintassi è ereditata da C. – emlai

+2

C, perché lo fai ?! – c1646091

2
int (Class::*f())(float,float); 

f è la funzione di prendere senza argomenti che tornano puntatore a funzione membro della classe Class takinf 2 galleggianti e di ritorno int.

e il modello versione:

  template <typename Type> 
     int (Type::*f())(float,float); 
3

È necessario questo prototipo:

template<typename TemplateClass> 
int (TemplateClass::*Testtest(TemplateClass &A)) (float,float) { } 
0

Rifiuto la premessa della tua domanda. Usa typedef. Oppure, in particolare, un tipo di caratteristica:

template <class T, class F> 
struct make_mem_fun { 
    typedef F T::*type; 
}; 

template<typename TemplateClass> 
typename make_mem_fun<TemplateClass, int(float, float)>::type 
Testtest(TemplateClass &A) 
{ 
    return &TemplateClass::Function; 
} 

Questo è il modo più semplice da capire che la sintassi contorta del ritorno in realtà il tipo. Con C++ 11, possiamo trasformarlo in un alias per eliminare il materiale typename ::type.

+0

* Perché * respingi la premessa della domanda? I typedef, come detto, non funzionano con i template - come dimostra il tuo uso di una struct come una sorta di work around. Personalmente preferirei sapere quale sia la sintassi di una funzione che restituisce una funzione pointer-to-member piuttosto che seppellire la mia ignoranza in una strana soluzione "sempre typedef", non solo per poterla implementare, ma così posso anche identificarlo. La conoscenza è così ben sepolta che anche le ricerche multiple non sono in grado di scavare, sperimentare fallito e sono stato costretto a chiedere su SO. – c1646091

+0

@ c1646091 Riesci a capire quale 'int (TemplateClass :: * TestTest (TemplateClass & A)) (float, float)' significa? Mi ci vorranno 10 minuti solo per analizzarlo. Capire cosa significa "make_mem_fun "? Pezzo di torta. – Barry

+0

@ c1646091 E come mostra la mia risposta, i typedef funzionano con i modelli.Questo è un typedef di template C++ 03. Diventa meno prolisso in C++ 11, ma non è come se non esistesse. – Barry