2012-11-12 6 views
5

cerco di specializzarsi un modello se una classe ha una speciale funzione membro come questo (che si trova qui in un altro esempio):modello per verificare l'esistenza di sovraccarico funzione membro

template <typename T> 
class has_begin 
{ 
    typedef char one; 
    typedef long two; 

    template <typename C> static one test(decltype(&C::AnyFunc)) ; 
    template <typename C> static two test(...); 

public: 
    enum { value = sizeof(test<T>(0)) == sizeof(char) }; 
    enum { Yes = sizeof(has_begin<T>::test<T>(0)) == 1 }; 
    enum { No = !Yes }; 
}; 

Questo metodo funziona bene fino a quando AnyFunc è sovraccaricato :

class B : public vector<int> 
{ 
public: 
    void AnyFunc() const; 
    void AnyFunc(); 
}; 

Come posso riscrivere il codice di prova per ottenere un "Sì" dal modello?

+0

Buona domanda. Un problema molto banale che può passare silenziosamente inosservato a causa di SFINAE. – iammilind

risposta

1

trovato la versione che funziona:

template <typename C> static one test(decltype(((C*)0)->AnyFunc())*) ; 

Se si desidera verificare l'oggetto ha la funzione const, utilizzare questo:

template <typename C> static one test(decltype(((const C*)0)->AnyFunc())*) ; 

questa versione non rileverà la funzione con argomenti:

class B : public std::vector<int> 
{ 
public: 
    //void AnyFunc() const; 
    //void AnyFunc(); 
    int AnyFunc(int); 
}; 
+1

@Klaus Ecco perché ho aggiunto '*' dopo 'decltype()' ... Ho controllato che funzionasse prima di postare: http://ideone.com/8Tli7t – PiotrNycz

+0

Dopo aver letto la seconda risposta, ho ottenuto la soluzione per l'esecuzione nel mio ambiente Molte grazie! – Klaus

+0

Sì, ho dimenticato il * dopo il decltype! Scusa per colpa mia! L'ho fatto funzionare dopo aver guardato dietro lo std :: add_pointer della seconda risposta. – Klaus

2

L'uso di un nome di funzione sovraccarico senza argomenti (13.4p1) deve essere risolto in un canto sovraccarico (13.4p4), altrimenti si verificherà un errore di sostituzione.

Se si esegue il test per l'esistenza di una funzione membro, allora si dovrebbe sapere gli argomenti che si intende chiamare con:

template <typename C> static one test(
     typename std::add_pointer<decltype(std::declval<C>().AnyFunc())>::type); 

In generale, è possibile utilizzare un modello variadic e un modello simile a result_of :

template <typename C, typename... Args> static one test(
     typename std::add_pointer<decltype(
      std::declval<C>(std::declval<Args>()...).AnyFunc())>::type); 

Utilizzando add_pointer permette a questo di lavorare con tipi restituiti dalle funzioni che non sono ammissibili come tipi di funzione argomento (es void).