2011-10-01 34 views
12

Me gustaría definir una especialización de plantilla C++ que se aplica a todas las subclases de una clase base dada. es posible?especialización de plantilla para todas las subclases

En particular, me gustaría hacer esto para el hash < de STL>. hash de <> se define como una plantilla parametrizada vacío, y una familia de especializaciones para tipos específicos:

template<class _Key> 
    struct hash { }; 

template<> 
    struct hash<char> 
    { 
    size_t 
    operator()(char __x) const 
    { return __x; } 
    }; 

template<> 
    struct hash<int> 
    { 
    size_t 
    operator()(int __x) const 
    { return __x; } 
    }; 
... 

me gusta definir algo como esto:

template<class Base> 
    struct hash { 
    size_t operator()(const Base& b) const { 
     return b.my_hash(); 
    } 
    }; 

class Sub : public Base { 
    public: 
    size_t my_hash() const { ... } 
}; 

y ser capaz de utilizarlo como esto:

hash_multiset<Sub> set_of_sub; 
set_of_sub.insert(sub); 

Sin embargo, mi plantilla hash entra en conflicto con la genérica de STL. ¿Hay alguna forma (tal vez usando rasgos) para definir una especialización de plantilla que se aplique a todas las subclases de una clase base dada (sin modificar las definiciones STL)?

Tenga en cuenta que sé que puedo hacer esto con algunos parámetros de plantilla adicionales siempre que se necesita esta especialización de hash, pero me gustaría evitar esto si es posible:

template<> 
    struct hash<Base> { 
    size_t operator()(const Base& b) const { 
     return b.my_hash(); 
    } 
    }; 

.... 

// similar specialization of equal_to is needed here... I'm glossing over that... 
hash_multiset<Sub, hash<Base>, equal_to<Base> > set_of_sub; 
set_of_sub.insert(sub); 
+0

si está en conflicto, ¿por qué no usar un espacio de nombres? – Arunmu

+1

Un posible duplicado de http://stackoverflow.com/questions/1032973/how-to-partially-specialize-a-class-template-for-all-derived-types –

+0

... donde la solución es nombrar todas las clases derivadas de una manera similar, que no es del todo satisfactoria. – jpalecek

Respuesta

1

La solución es utilizar SFINAE para decidir si permite o no su especialización dependiendo de la estructura de herencia de la clase. En Boost puede usar enable_if y is_base_of para implementar esto.

+0

Me temo que no puede usar 'enable_if' en este caso particular. – jpalecek

+0

jpalecek: ¿Por qué no? Por cierto, si impulsar es la respuesta aquí, puede que no me ayude de todos modos, ya que mi lugar de trabajo restringe las bibliotecas que podemos usar, y boost :: enable_if no es parte del subconjunto prescrito. –

+0

Luego puede que tenga que hacer las suyas propias, pero debería poder obtener algo que funcione como desee utilizando SFINAE. – KayEss

0

Esto era lo mejor que podía hacer:

template<> 
    struct hash<Sub> : hash<Base> { 
    }; 

estoy un poco preocupado de que yo no tenía que hacer operator() virtual, aunque .

Cuestiones relacionadas