12

I'm trying to check if a class has a method operator==. I found a solution with SFINAE here and it's working fine with the class I make.

It looks like this :

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

But, when I try :

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

Then it returns false while I was expecting it to return true. Why is this ?

Community
  • 1
  • 1
Malcolm
  • 662
  • 7
  • 29
  • 1
    About the question you had in there before your edit (what the three dots mean), look at this question: http://stackoverflow.com/questions/1657883/variable-number-of-arguments-in-c – Anedar Feb 15 '16 at 22:21
  • 1
    What if `class C {...}; bool operator==(const C& a, const C& b) {...}`? Your code will say there is no operator==, because there isn't one within the class. – user253751 Feb 15 '16 at 22:28

4 Answers4

19

int is not a class-type and has no member operator==, which is what you check for with your &C::operator==. Thus, the test yields a "no". As others correctly pointed out, your test would also be negative for classes with only a non-member operator==.

How to correctly check whether an operator== exists has been asked here: How to check whether operator== exists?

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • 1
    @πάνταῥεῖ It doesn't tell him why his approach fails, so at least I won't Mjölnir it. But I agree, that was an easy 80 rep. – Baum mit Augen Feb 15 '16 at 22:25
  • 1
    We're sons of Odin and have to be responsibly users of our powers. Well achieved, and congrats for the +80 (one 10 was from my side). – πάντα ῥεῖ Feb 15 '16 at 22:27
10

Your immediate approach is flawed (or incomplete) for at least two fundamental reasons.

Firstly, your method checks whether class C has a member named operator ==. Non-class types will not pass this test, since they have no members whatsoever. And int is a non-class type.

Secondly, this approach by itself does not detect classes for which operator == is implemented as a standalone function. For example, your test will say that std::string has no == operator. It is true that std::string has no such member, yet you can compare std::string's for equality using the standalone operator ==. So, even if int somehow were a class type, it still does not mean that it would implement operator == as a member function.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
4

Your test does not test if the expression C==C is valid. It tests if your class C has an C::operator==. Since int is no class it has no class-members.

Try testing e.g. typeof(C()==C())

Anedar
  • 4,235
  • 1
  • 23
  • 41
0

If you use c++11 you can use decltype which will make the implementation a lot easier:

#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
}
W.F.
  • 13,888
  • 2
  • 34
  • 81