2016-02-15 12 views
12

Sto provando a verificare se una classe ha un metodo operator==. Ho trovato una soluzione con SFINAE here e funziona perfettamente con la classe che faccio.int ha un operatore ==

Ecco come si presenta:

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

    template <typename C> static one test(typeof(&C::operator==)) ; 
    template <typename C> static two test(...); 


public: 
    enum { value = sizeof(test<T>(0)) == sizeof(char) }; 
}; 

Ma, quando provo:

std::cout << comparable<int>::value << std::endl; 

Poi restituisce false, mentre io mi aspettavo di restituire true. Perchè è questo ?

+1

Circa la questione si aveva in là prima della modifica (che cosa significano i tre punti), guarda questa domanda: http://stackoverflow.com/questions/1657883/variable-number-of-arguments-in-c – Anedar

+1

Cosa succede se 'classe C {...}; bool operator == (const C & a, const C & b) {...} '? Il tuo codice dirà che non c'è operatore ==, perché non ce n'è uno nella classe. – immibis

risposta

19

int non è un tipo di classe e non ha alcun membro operator==, che è ciò che si verifica con il &C::operator==. Pertanto, il test produce un "no" "". Come altri correttamente hanno sottolineato, il test sarebbe anche negativo per le classi con solo un non membro operator==.

Come controllare correttamente se un operator== esiste è stato chiesto qui: How to check whether operator== exists?

+3

Dupe in realtà ?? –

+1

@ πάνταῥεῖ Non gli dice perché il suo approccio fallisce, quindi almeno non lo farò Mjölnir. Ma sono d'accordo, è stato un semplice 80 rep. –

+1

Siamo figli di Odino e dobbiamo essere responsabilmente utenti dei nostri poteri. Ben realizzato e complimenti per il +80 (un 10 era dalla mia parte). –

4

Il test non verifica se l'espressione C==C è valida. Verifica se la tua classe C ha un C::operator==. Dal int non esiste una classe che non abbia membri della classe.

Provare ad es. typeof(C()==C())

10

L'approccio immediato è imperfetto (o incompleto) per almeno due motivi fondamentali.

In primo luogo, i vostri controlli metodo se classeC ha un membro nome operator ==. I tipi non di classe non supereranno questo test, poiché non hanno membri di sorta. E int è un tipo non di classe.

In secondo luogo, questo approccio di per sé non rileva classi per le quali operator == è implementato come funzione autonoma. Ad esempio, il tuo test dirà che std::string non ha l'operatore ==. È vero che lo std::string non ha un membro del genere, ma puoi confrontare lo std::string per l'uguaglianza utilizzando lo standalone operator ==. Quindi, anche se int fosse in qualche modo un tipo di classe, non significa ancora che implementerebbe operator == come funzione membro.

0

Se si utilizza C++ 11 è possibile utilizzare decltype che renderà l'applicazione molto più facile:

#include <iostream> 
#include <type_traits> 

using namespace std; 

template <class T, class Sfinae = void> 
class comparable { 
public: 
    static constexpr bool value = false; 
}; 

template <class T> 
class comparable <T, typename enable_if<is_same<decltype(declval<T>() == declval<T>()), bool>::value>::type> { 
public: 
    static constexpr bool value = true; 
}; 

class A { 
public: 
    bool operator==(const A &) { 
     return true; 
    } 
}; 

class B { 
}; 

int main() { 
    cout << comparable<int>::value << endl; // output: 1 
    cout << comparable<A>::value << endl; // output: 1 
    cout << comparable<B>::value << endl; // output: 0 
} 
Problemi correlati