Quiero especializar parcialmente una plantilla existente que no puedo cambiar (std::tr1::hash
) para una clase base y todas las clases derivadas. La razón es que estoy usando el patrón de plantilla curiosamente recurrente para el polimorfismo, y la función hash se implementa en la clase base CRTP. Si sólo desea especializarse parte de una clase de la base CRTP, entonces es fácil, sólo puedo escribir:¿Cómo se especializa parcialmente una plantilla de clase para todos los tipos derivados?
namespace std { namespace tr1 {
template <typename Derived>
struct hash<CRTPBase<Derived> >
{
size_t operator()(const CRTPBase<Derived> & base) const
{
return base.hash();
}
};
} }
Pero esta especialización no coincide con las clases derivadas reales, solamente CRTPBase<Derived>
. Lo que quiero es una forma de escribir una especialización parcial para Derived
si y solo si deriva de CRTPBase<Derived>
. Mi pseudo-código es
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();
}
};
} }
... pero eso no funciona porque el compilador no puede decir que es enable_if<condition, Derived>::type
Derived
. Si pudiera cambiar std::tr1::hash
, agregaría otro parámetro de plantilla ficticio para usar boost::enable_if
, como lo recomienda la documentación enable_if
, pero obviamente no es una solución muy buena. ¿Hay alguna forma de solucionar este problema? ¿Debo especificar una plantilla hash personalizada en cada unordered_set
o unordered_map
que creo, o me especializo por completo hash
para cada clase derivada?
Se ve bien, gracias. – Doug