Я хочу частично специализировать существующий шаблон, который я не могу изменить (std::tr1::hash
) для базового класса и всех производных классов. Причина в том, что я использую любопытно повторяющийся шаблон для полиморфизма, а хеш-функция реализована в базовом классе CRTP. Если я хочу только частично специализироваться на базовом классе CRTP, то это легко, я могу просто написать:
namespace std { namespace tr1 {
template <typename Derived>
struct hash<CRTPBase<Derived> >
{
size_t operator()(const CRTPBase<Derived> & base) const
{
return base.hash();
}
};
} }
Но эта специализация не соответствует фактическим производным классам, только CRTPBase<Derived>
. То, что я хочу, это способ написать частичную специализацию для Derived
тогда и только тогда, когда она происходит от CRTPBase<Derived>
. Мой псевдокод
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();
}
};
} }
... но это не работает, потому что компилятор не может сказать, что enable_if<condition, Derived>::type
это Derived
. Если бы я мог изменить std::tr1::hash
, я бы просто добавил еще один фиктивный параметр шаблона для использования boost::enable_if
, как рекомендовано документацией enable_if
, но это, очевидно, не очень хорошее решение. Есть ли способ обойти эту проблему? Нужно ли указывать пользовательский шаблон хеша для каждого unordered_set
или unordered_map
, который я создаю, или полностью специализировать hash
для каждого производного класса?