2009-03-15 13 views
22

¿Cómo permito que la implementación de STL recupere mis tipos personalizados? En MSVC, hay una clase std::tr1::hash, que pueden especializarse en parte mediante el uso de¿Cómo extender std :: tr1 :: hash para tipos personalizados?

namespace std 
{ 
    namespace tr1 
    { 
     template <> 
     struct hash<MyType> 
     { ... }; 
    } 
} 

pero es esta la forma recomendada? Además, ¿esto también funciona con la implementación de GCC? Para boost::hash, es suficiente para proporcionar una función gratuita size_t hash_value (const MyType&), ¿hay algo similar para la implementación de TR1?

+0

¿Hay alguna manera de extender std :: hash para los tipos definidos por el usuario con constructores de copia privada? Además, ¿hay alguna manera de extenderlo con un operador() que toma una referencia ref en lugar de val? –

+0

¿Cuál es el problema con la especialización de plantillas? No tomas una copia de tu objeto (lo pasas por referencias), así que no hay problema, y ​​el operador() toma una referencia o valor, lo que quieras. Mire la respuesta de Phil Nash, que toma el objeto como const ref. – Anteru

Respuesta

4

Sí, esto también funcionará para GCC. Lo estoy usando en un proyecto más grande y funciona sin problemas. También puede proporcionar su propia clase de hash personalizada para los contenedores TR1, pero se especifica que std :: tr1 :: hash <> es la clase de hashing predeterminada. Especializarlo para tipos personalizados parece ser la forma natural de extender la funcionalidad de hash estándar.

3

Como no está agregando espacio de nombre de biblioteca std, pero solo proporciona las especializaciones, entonces está perfectamente bien.

Si desea proporcionar un método de hashing más genérico (por ejemplo, hash para las tuplas en general), eche un vistazo a Boost Fusion. Here is a simple example, que funcionará para la mayoría de los casos (probablemente con la excepción para la tupla de tuplas)

21

Estaba tratando de encontrar la sintaxis exacta para hacer esto con los contenedores asociativos desordenados (también usando GCC, ya que el OP era preguntando) y dale a esta pregunta.

Desafortunadamente no bajé al nivel de detalle que quería. Al mirar a través de los encabezados de gcc cómo han implementado las funciones hash estándar, lo hice funcionar. En vista de la escasez de ejemplos (al menos en el momento de la escritura) en la web pensé que esto sería un lugar tan bueno como cualquier otro para publicar mi propio ejemplo (que puedo confirmar obras con GCC):


namespace std { namespace tr1 
{ 
    template <> 
    struct hash<MyType> : public unary_function<MyType, size_t> 
    { 
     size_t operator()(const MyType& v) const 
     { 
      return /* my hash algorithm */; 
     } 
    }; 
}} 

(aviso no son dos espacios de nombres aquí - eso es sólo mi convención para colapsar los espacios de nombres anidados)

0

El siguiente fragmento de código se muestra cómo se especializan std::tr1::unordered_map a la cartografía boost::const_string<char> a void* análoga con la forma es ordenada std::string.

#include <boost/const_string/const_string.hpp>  
typedef class boost::const_string<char> csc; 

namespace std 
{ 
namespace tr1 
{ 
template <> 
struct hash<csc> { 
public: 
    size_t operator()(const csc & x) const { 
     return std::_Hash_impl::hash(x.data(), x.size()); 
    } 
}; 
} 
} 

typedef std::tr1::unordered_map<csc, void*> Map; 
typedef Map::value_type Dual; ///< Element Type. 
Cuestiones relacionadas