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