C ++ Solution 11. Just change the return type so that it is only a valid type that has .hash . In addition, we use the comma operator, so although the compiler checks that it can evaluate declval<T>.hash() , it will actually ignore it and use the type true , which of course is bool , the type you want.
 template <class T> auto equals(const T &x, const T &y) -> decltype(declval<T>.hash(), true) { return x.hash() == y.hash() && x == y; } 
I believe this is called Expression SFINAE.
More details:
decltype(X,Y) same as decltype(Y) (thanks to the comma operator). This means that my return type here is basically decltype(true) , i.e. bool , optional. Why do I have declval<T>.hash() ? Isn't that a waste of space?
The answer is that this is a test that T has a hash method. If this test fails, then the calculation of the return type fails, and therefore the function is not considered as a valid overload, and the compiler will look elsewhere.
Finally, if you have not seen declval , this is a really useful way to create an object of type T in an invaluable context (e.g. decltype ). You might be tempted to write T() to build T and therefore use T().hash() to call hash . But this will not work if T does not have a default constructor. declval solves this.
 source share