2016-02-15 7 views
12

Ich versuche zu überprüfen, ob eine Klasse eine Methode operator== hat. Ich fand eine Lösung mit SFINAE here und es funktioniert gut mit der Klasse, die ich mache.hat Int einen Operator ==

Es sieht wie folgt aus:

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) }; 
}; 

Aber, wenn ich versuche:

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

Dann gibt es falsch, während ich es erwartete wahr zurückzukehren. Warum ist das ?

+1

Über die Frage, die Sie vor der Bearbeitung dort hatte (was die drei Punkte bedeuten), schauen diese Frage: http://stackoverflow.com/questions/1657883/variable-number-of-arguments-in-c – Anedar

+1

Was ist, wenn "Klasse C {...}; bool operator == (const C & a, const C & b) {...} '? Ihr Code sagt, dass es keinen Operator == gibt, weil es keinen innerhalb der Klasse gibt. – immibis

Antwort

19

int ist kein Klassen-Typ und hat kein Mitglied operator==, nach dem Sie mit Ihrer &C::operator== suchen. Somit ergibt der Test eine "no". Wie andere korrekt angemerkt haben, wäre Ihr Test auch negativ für Klassen mit nur einem Nichtmitglied operator==.

Wie richtig zu prüfen, ob ein operator== existiert hier gefragt wurde: How to check whether operator== exists?

+3

Dupe eigentlich ?? –

+1

@ πάνταῥεῖ Es sagt ihm nicht, warum seine Herangehensweise fehlschlägt, also werde ich es zumindest nicht mjölnir. Aber ich stimme zu, das war ein einfacher 80er. –

+1

Wir sind Söhne von Odin und müssen verantwortungsvoll unsere Kräfte nutzen. Gut erreicht, und Gratulation für die +80 (eine 10 war von meiner Seite). –

4

Ihr Test prüft nicht, wenn der Ausdruck C==C gültig ist. Es testet, ob Ihre Klasse C eine C::operator== hat. Da int keine Klasse ist, hat es keine Klassenmitglieder.

Versuche z. typeof(C()==C())

10

Ihr sofortiger Ansatz ist aus mindestens zwei grundlegenden Gründen fehlerhaft (oder unvollständig).

Erstens Ihre Methode überprüft, ob KlasseC einMitglied hat operator == genannt. Nicht-Klassen-Typen werden diesen Test nicht bestehen, da sie überhaupt keine Mitglieder haben. Und int ist ein Nicht-Klassen-Typ.

Zweitens erkennt dieser Ansatz selbst keine Klassen, für die operator == als eigenständige Funktion implementiert ist. Zum Beispiel wird Ihr Test sagen, dass std::string keinen == Operator hat. Es ist wahr, dass std::string kein solches Mitglied hat, aber Sie können std::string für Gleichheit mit dem Standalone operator == vergleichen. Also, auch wenn int irgendwie ein Klassen-Typ wäre, bedeutet es immer noch nicht, dass es operator == als eine Member-Funktion implementieren würde.

0

Wenn Sie C++ 11 können Sie decltype verwenden, die die Implementierung viel leichter machen wird:

#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 
}