How to check whether operator== exists?
C++03
The 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
and null reference trick when we have decltype
and std::declval
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(std::declval<T>() < std::declval<Arg>()), No>::value };
};
}
Demo
Have a look at Boost's Concept Check Library (BCCL) http://www.boost.org/doc/libs/1_46_1/libs/concept_check/concept_check.htm.
It enables you to write requirements that a class must match in order for the program to compile. You're relatively free with what you can check. For example, verifying the presence of operator==
of a class Foo would write as follow:
#include <boost/concept_check.hpp>
template <class T>
struct opEqualExists;
class Foo {
public:
bool operator==(const Foo& f) {
return true;
}
bool operator!=(const Foo& f) {
return !(*this == f);
}
// friend bool operator==(const Foo&, const Foo&);
// friend bool operator!=(const Foo&, const Foo&);
};
template <class T>
struct opEqualExists {
T a;
T b;
// concept requirements
BOOST_CONCEPT_USAGE(opEqualExists) {
a == b;
}
};
/*
bool operator==(const Foo& a, const Foo& b) {
return true; // or whatever
}
*/
/*
bool operator!=(const Foo& a, const Foo& b) {
return ! (a == b); // or whatever
}
*/
int main() {
// no need to declare foo for interface to be checked
// declare that class Foo models the opEqualExists concept
// BOOST_CONCEPT_ASSERT((opEqualExists<Foo>));
BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Foo>)); // need operator!= too
}
This code compiles fine as long as one of the two implementations of operator==
is available.
Following @Matthieu M. and @Luc Touraille advice, I updated the code snippet to provide an example of boost::EqualityComparable
usage. Once again, please note that EqualityComparable forces you to declare operator!=
too.