2016-02-15 14 views
12

Próbuję sprawdzić, czy klasa ma metodę operator==. Znalazłem rozwiązanie z SFINAE here i działa dobrze z klasą, którą wykonuję.ma int mieć operatora ==

Wygląda to tak:

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

Ale gdy próbuję:

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

wówczas zwraca fałsz, a ja spodziewałem się wrócić prawdziwe. Dlaczego to ?

+1

o pytaniu trzeba było tam przed edytować (co trzy kropki na myśli), spojrzeć na to pytanie: http://stackoverflow.com/questions/1657883/variable-number-of-arguments-in-c – Anedar

+1

Co jeśli 'class C {...}; operator bool == (const C & a, const C & b) {...} '? Twój kod powie, że nie ma operatora ==, ponieważ nie ma go w klasie. – immibis

Odpowiedz

19

int nie jest typem klasowym i nie ma członka operator==, o czym można sprawdzić za pomocą numeru &C::operator==. Tak więc, test daje "nie". Jak inni słusznie zauważyli, twój test byłby również negatywny w przypadku klas, w których uczestniczy tylko osoba spoza domeny operator==.

Jak prawidłowo sprawdzić, czy istnieje operator== został poproszony tutaj: How to check whether operator== exists?

+3

Dupe faktycznie? –

+1

@ πάνταῥεῖ To nie mówi mu, dlaczego jego podejście zawodzi, więc przynajmniej nie będę Mjölnir go. Ale zgadzam się, to był łatwy 80 przedstawicieli. –

+1

Jesteśmy synami Odyna i musimy być odpowiedzialnymi użytkownikami naszych mocy. Dobrze osiągnięty, i gratulacje dla +80 (jeden 10 był z mojej strony). –

4

test nie sprawdza czy wyrażenie C==C jest prawidłowy. Testuje, czy klasa C ma numer C::operator==. Ponieważ int nie ma klasy, nie ma członków klasy.

Spróbuj przetestować np. typeof(C()==C())

10

Twoje bezpośrednie podejście jest wadliwe (lub niekompletne) z co najmniej dwóch podstawowych powodów.

Po pierwsze, twoje metoda sprawdza czy klasaC ma człon nazwie operator ==. Typy nieklasyczne nie przejdą tego testu, ponieważ nie mają żadnych członków. I int jest typem nieklasowanym.

Po drugie, to podejście samo w sobie nie wykrywa klas, dla których zaimplementowano operator == jako samodzielną funkcję. Na przykład twój test powie, że std::string nie ma operatora ==. Prawdą jest, że std::string nie ma takiego elementu, ale można porównać std::string dla równości przy użyciu autonomicznego operator ==. Tak więc, nawet jeśli int w jakiś sposób był typem klasy, nadal nie oznacza to, że zaimplementowałoby to jako funkcję składową operator ==.

0

Jeśli używasz C++ 11 można użyć decltype co uczyni realizację dużo łatwiejsze:

#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 
} 
Powiązane problemy