Chcę częściowo specjalizować istniejący szablon, którego nie mogę zmienić (std::tr1::hash
) dla klasy bazowej i wszystkich klas pochodnych. Powodem jest to, że używam ciekawie powtarzającego się wzorca szablonu dla polimorfizmu, a funkcja skrótu jest zaimplementowana w klasie bazowej CRTP. Jeśli chcę tylko częściowo specjalizują dla klasy podstawa CRTP, to proste, mogę tylko napisać:Jak częściowo specjalizować szablon klasy dla wszystkich typów pochodnych?
namespace std { namespace tr1 {
template <typename Derived>
struct hash<CRTPBase<Derived> >
{
size_t operator()(const CRTPBase<Derived> & base) const
{
return base.hash();
}
};
} }
Ale ta specjalizacja nie pasuje do rzeczywistych klas pochodnych, tylko CRTPBase<Derived>
. To, czego chcę, to sposób na napisanie częściowej specjalizacji dla Derived
wtedy i tylko wtedy, gdy pochodzi od CRTPBase<Derived>
. Mój pseudo-kod jest
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();
}
};
} }
... ale to nie działa, ponieważ kompilator nie może powiedzieć, że enable_if<condition, Derived>::type
jest Derived
. Gdybym mógł zmienić std::tr1::hash
, po prostu dodałbym kolejny fałszywy parametr szablonu do użycia boost::enable_if
, zgodnie z zaleceniami zawartymi w dokumentacji enable_if
, ale to oczywiście nie jest dobre rozwiązanie. Czy istnieje sposób obejścia tego problemu? Czy muszę określić niestandardowy szablon skrótu na każdym unordered_set
lub unordered_map
utworzyć lub w pełni wyspecyfikować hash
dla każdej klasy pochodnej?
Wygląda dobrze, dzięki. – Doug