Is there anyway to specialize a template based on the members of a parameter in C++?
c++, template-meta-programming, template-specialization, templates
Solution
Here's an example from my own code. As you might guess from one of the structure names this is based on the principle that Substitution Failure is Not an Error. The structure `has_member_setOrigin` defines two versions of `test`. The first one cannot be satisfied if `U` does not have a member `setOrigin`. Since that is not an error in a template substitution it just acts as if it does not exist. The resolution order for polymorphic functions thus finds `test(...)` which would otherwise have a lower priority. The `value` is then determined by the return type of `test`.
This is followed by two definitions of `callSetOrigin` (equivalent to your `equals`) using the `enable_if` template. If you examine `enable_if` you'll see that if the first template argument is true then `enable_if<...>::type` is defined, otherwise it is not. This again creates a substitution error in one of the definitions of `callSetOrigin` such that only one survives.
template <typename V>
struct has_member_setOrigin
{
template <typename U, void (U::*)(const Location &)> struct SFINAE {};
template <typename U> static char test(SFINAE<U, &U::setOrigin>*);
template <typename U> static int test(...);
static const bool value = sizeof(test<V>(0)) == sizeof(char);
};
template<typename V>
void callSetOrigin(typename enable_if <has_member_setOrigin<V>::value, V>::type &p, const Location &loc) const
{
p.setOrigin(loc);
}
template<typename V>
void callSetOrigin(typename enable_if <!has_member_setOrigin<V>::value, V>::type &p, const Location &loc) const
{
}
Forgot I provided a definition of `enable_if` as well:
#ifndef __ENABLE_IF_
#define __ENABLE_IF_
template<bool _Cond, typename _Tp>
struct enable_if
{ };
template<typename _Tp>
struct enable_if<true, _Tp>
{ typedef _Tp type; };
#endif /* __ENABLE_IF_ */
Problem
Is there anyway to specialize a template like this, making the specialization apply only if T has a member function `hash`? (Note this is only an example of what I am trying to do. I know that it would make more sense for each class that has a `hash` function to check it on its own in the `operator==` member function, but I just want to know if this kind of thing is possible.) ``` template <class T> bool equals(const T &x, const T &y) { return x == y; } template <class T> // somehow check if T has a member function 'hash' bool equals<T>(const T &x, const T &y) { return x.hash() == y.hash() && x == y; } ``` I would prefer a pre-C++11 solution if possible.