I want to partially specialize an existing template that I cannot change (std::tr1::hash
) for a base class and all derived classes. The reason is that I'm using the curiously-recurring template pattern for polymorphism, and the hash function is implemented in the CRTP base class. If I only want to partially specialize for a the CRTP base class, then it's easy, I can just write:
namespace std { namespace tr1 {
template <typename Derived>
struct hash<CRTPBase<Derived> >
{
size_t operator()(const CRTPBase<Derived> & base) const
{
return base.hash();
}
};
} }
But this specialization doesn't match actual derived classes, only CRTPBase<Derived>
. What I want is a way of writing a partial specialization for Derived
if and only if it derives from CRTPBase<Derived>
. My pseudo-code is
namespace std { namespace tr1 {
template <typename Derived>
struct hash<typename boost::enable_if<std::tr1::is_base_of<CRTPBase<Derived>, Derived>,
Derived>::type>
{
size_t operator()(const CRTPBase<Derived> & base) const
{
return base.hash();
}
};
} }
...but that doesn't work because the compiler can't tell that enable_if<condition, Derived>::type
is Derived
. If I could change std::tr1::hash
, I'd just add another dummy template parameter to use boost::enable_if
, as recommended by the enable_if
documentation, but that's obviously not a very good solution. Is there a way around this problem? Do I have to specify a custom hash template on every unordered_set
or unordered_map
I create, or fully specialize hash
for every derived class?