BЈовић BЈовић - 2 months ago 6
C++ Question

How to check whether operator== exists?

I am trying to create an example, which would check the existence of the

operator==
(member or, non-member function). To check whether a class has a member
operator==
is easy, but how to check whether it has a non-member
operator==
?

This is what I have to far :

#include <iostream>

struct A
{
int a;

#if 0
bool operator==( const A& rhs ) const
{
return ( a==rhs.a);
}
#endif
};
#if 1
bool operator==( const A &l,const A &r )
{
return ( l.a==r.a);
}
#endif


template < typename T >
struct opEqualExists
{
struct yes{ char a[1]; };
struct no { char a[2]; };

template <typename C> static yes test( typeof(&C::operator==) );
//template <typename C> static yes test( ???? );
template <typename C> static no test(...);

enum { value = (sizeof(test<T>(0)) == sizeof(yes)) };
};

int main()
{
std::cout<<(int)opEqualExists<A>::value<<std::endl;
}


Is it possible to write a test function to test the existence of non-member
operator==
?
If yes, how?

btw I have checked similar questions, but haven't found a proper solution :

Is it possible to use SFINAE/templates to check if an operator exists?

This is what I tried :

template <typename C> static yes test( const C*,bool(*)(const C&,constC&) = &operator== );


but the compilation fails if the non-member operator== is removed

Answer

C++03

Following trick works. And it can be used for all such operators:

namespace CHECK
{
  class No { bool b[2]; };
  template<typename T, typename Arg> No operator== (const T&, const Arg&);

  bool Check (...);
  No& Check (const No&);

  template <typename T, typename Arg = T>
  struct EqualExists
  {
    enum { value = (sizeof(Check(*(T*)(0) == *(Arg*)(0))) != sizeof(No)) };
  };  
}

Usage:

CHECK::EqualExists<A>::value;

The 2nd template typename Arg is useful for some special cases like A::operator==(short), where it's not similar to class itself. In such cases the usage is:

CHECK::EqualExists<A, short>::value
//                    ^^^^^ argument of `operator==`

Demo.


C++11

We need not use sizeof trick when we have decltype

namespace CHECK
{
  struct No {}; 
  template<typename T, typename Arg> No operator== (const T&, const Arg&);

  template<typename T, typename Arg = T>
  struct EqualExists
  {
    enum { value = !std::is_same<decltype(*(T*)(0) == *(Arg*)(0)), No>::value };
  };  
}

Demo

Comments