Espacios de nombres
Variantes
Acciones

std::hash

De cppreference.com
< cpp‎ | utility
 
 
Biblioteca de servicios
 
 
Definido en el archivo de encabezado <functional>
template<class Key >
struct hash;
(desde C++11)

std::hash es una función de dispersión o función hash. Cada especialización de esta plantilla es ya sea habilitada ("pura") o deshabilitada ("envenenada"). Para cada tipo Key para el cual ni la biblioteca ni el usuario proporcionan una especialización habilitada std::hash<Key>, esa especialización existe y está deshabilitada. Las especializaciones deshabilitadas no satisfacen a Hash, no satisfacen a FunctionObject, y los siguientes valores son todos false:

En otras palabras, existen, pero no pueden usarse.

Las especializaciones habilitadas de la plantilla hash definen una función objeto que implementa una función de dispersión o función hash. Instancias de esta función satisfacen a Hash. En particular, definen un operador, operator()const que:

  1. Acepta un sólo parámetro de tipo Key.
  2. Devuelve un valor de tipo size_t que representa el valor de dispersión del parámetro.
  3. No inicia excepciones cuando se le llama.
  4. Para dos parámetros k1 y k2 que son iguales, std::hash<Key>()(k1)== std::hash<Key>()(k2).
  5. Para dos parámetros distintos k1 y k2 que no son iguales, la probabilidad de que std::hash<Key>()(k1)== std::hash<Key>()(k2) deberá ser muy pequeña, acercándose a 1.0/std::numeric_limits<size_t>::max().

Todas las especializaciones totales y parciales de hash proporcionadas por la biblioteca estándar son DefaultConstructible, CopyAssignable, Swappable y Destructible. Las especializaciones de hash proporcionadas por el usuario también deben cumplir con esos requerimientos.

Los contenedores asociativos no ordenados std::unordered_set, std::unordered_multiset, std::unordered_map, std::unordered_multimap usan especializaciones de la plantilla std::hash como la función de dispersión por defecto.

Contenido

[editar]Notas

Las funciones de dispersión actuales dependen de la implementación y no se requiere que satisfagan ningunos otros criterios de calidad excepto aquellos especificados anteriormente. Notablemente, algunas implementaciones usan funciones de dispersión triviales (de identidad) las cuales corresponden un entero consigo mismas. En otras palabras, estas funciones de dispersión están designadas para funcionar con contenedores asociativos no ordenados, pero no como valores de dispersión criptográficos, por ejemplo.

De las funciones de dispersión solamente se requiere que produzcan el mismo resultado para la misma entrada dentro de una sola ejecución de un programa; esto permite salted hashes que previenen colisiones de ataques de denegación de servicio.(desde C++14)

No hay especialización para cadenas de C. std::hash<constchar*> produce un valor de dispersión del valor del puntero (la dirección de memoria), no examina el contenido del array de caracteres.

Tipos miembro

Tipo miembro Definición
argument_type(en desuso en C++17)Key
result_type(en desuso en C++17)std::size_t
(hasta C++20)

[editar]Funciones miembro

Construye una función objeto de dispersión
(función miembro pública)
Calcula el valor de dispersión del argumento
(función miembro pública)

[editar]Especializaciones estándar para los tipos básicos

Definido en el archivo de encabezado <functional>
template<>struct hash<bool>;

template<>struct hash<char>;
template<>struct hash<signedchar>;
template<>struct hash<unsignedchar>;
template<>struct hash<char8_t>;        // C++20
template<>struct hash<char16_t>;
template<>struct hash<char32_t>;
template<>struct hash<wchar_t>;
template<>struct hash<short>;
template<>struct hash<unsignedshort>;
template<>struct hash<int>;
template<>struct hash<unsignedint>;
template<>struct hash<long>;
template<>struct hash<longlong>;
template<>struct hash<unsignedlong>;
template<>struct hash<unsignedlonglong>;
template<>struct hash<float>;
template<>struct hash<double>;
template<>struct hash<longdouble>;
template<>struct hash<std::nullptr_t>;

template<class T >struct hash<T*>;

Además de lo anterior, la biblioteca estándar proporciona especializaciones para todos los tipos de enumeraciones (con ámbito o sin ámbito). Estas pueden implementarse (aunque no se requiere) como std::hash<std::underlying_type<Enum>::type>.

La biblioteca estándar proporciona especializaciones habilitadas de std::hash para std::nullptr_t y todos los tipos aritméticos no calificados-cv (incluyendo cualquier tipo entero extendido), todos los tipos de enumeraciones, y todos los tipos puntero.

Cada archivo de encabezado de la biblioteca estándar que declare la plantilla std::hash proporciona todas las especializaciones habilitadas descritas anteriormente. Estos encabezados incluyen <string>, <system_error>, <bitset>, <memory>, <typeindex>, <vector>, <thread>, <optional>, <variant>, <string_view>(desde C++17), <coroutine>(desde C++20).

Todas las funciones miembro de todas las especializaciones de la biblioteca estándar de esta plantilla son noexcept excepto las funciones miembro de std::hash<std::optional>, std::hash<std::variant>, y std::hash<std::unique_ptr>

(desde C++17)

[editar]Especializaciones estándar para los tipos de las bibliotecas

Apoyo de generación de dispersión para cadenas
(especialización de plantilla de clase)[editar]
Apoyo de generación de dispersión para std::error_code.
(especialización de plantilla de clase)[editar]
Apoyo de generación de dispersión para std::bitset.
(especialización de plantilla de clase)[editar]
Apoyo de generación de dispersión para std::unique_ptr.
(especialización de plantilla de clase)[editar]
Apoyo de generación de dispersión para std::shared_ptr.
(especialización de plantilla de clase)[editar]
Apoyo de generación de dispersión para std::type_index.
(especialización de plantilla de clase)[editar]
Apoyo de generación de dispersión para std::vector<bool>
(especialización de plantilla de clase)
Apoyo de generación de dispersión para std::thread::id
(especialización de plantilla de clase)
Especializa el algoritmo std::hash.
(especialización de plantilla de clase)[editar]
Especializa el algoritmo std::hash.
(especialización de plantilla de clase)[editar]
Apoyo de generación de dispersión para vistas sobre cadena
(especialización de plantilla de clase)[editar]
Apoyo de generación de dispersión para std::error_condition
(especialización de plantilla de clase)[editar]

Nota: Especializaciones adicionales para std::pair y los tipos de contenedores estándar, así como las funciones de utilería para componer valores de dispersión se encuentran disponibles en boost.hash

[editar]Ejemplo

#include <iostream>#include <iomanip>#include <functional>#include <string>#include <unordered_set>   struct S {std::string nombre;std::string apellido;};bool operator==(const S& lhs, const S& rhs){return lhs.nombre== rhs.nombre&& lhs.apellido== rhs.apellido;}   // Una función de dispersión personalizada puede ser una función objeto por sí sola:struct MiHash {std::size_t operator()(S const& s)constnoexcept{std::size_t h1 = std::hash<std::string>{}(s.nombre);std::size_t h2 = std::hash<std::string>{}(s.apellido);return h1 ^(h2 <<1);// o usar boost::hash_combine (véase Discusión)}};   // Una especialización personalizada de std::hash// puede inyectarse en el espacio de nombres stdnamespace std {template<>struct hash<S>{std::size_t operator()(S const& s)constnoexcept{std::size_t h1 = std::hash<std::string>{}(s.nombre);std::size_t h2 = std::hash<std::string>{}(s.apellido);return h1 ^(h2 <<1);// o usar boost::hash_combine}};}   int main(){   std::string str ="Conoce al nuevo jefe...";std::size_t str_hash = std::hash<std::string>{}(str);std::cout<<"hash("<<std::quoted(str)<<") = "<< str_hash <<'\n';   S obj ={"Aquiles", "Pinto"};// Usando la función objeto por sí solastd::cout<<"hash("<<std::quoted(obj.nombre)<<','<<std::quoted(obj.apellido)<<") = "<< MiHash{}(obj)<<" (usando MiHash)\n o "<< std::hash<S>{}(obj)<<" (usando la especialización de std::hash<S> inyectada)\n";   // Una función de dispersión personalizada hace posible// el uso de tipos personalizados en contenedores no ordenados.// El ejemplo usaría la especialización std::hash<S> inyectada de arriba,// para usar MiHash en su lugar, pasarla como un segundo argumento de plantillastd::unordered_set<S> nombres ={obj, {"Pito", "Pérez"}, {"Sancho", "Panza"}};for(auto& s: nombres)std::cout<<std::quoted(s.nombre)<<' '<<std::quoted(s.apellido)<<'\n';}

Posible salida:

hash("Conoce al nuevo jefe...") = 1861821886482076440 hash("Aquiles","Pinto") = 17622465712001802105 (usando MiHash) o 17622465712001802105 (usando la especialización de std::hash<S> inyectada) "Sancho" "Panza" "Pito" "Pérez" "Aquiles" "Pinto"

[editar]Informes de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
LWG 2148 C++11 Faltaban las especializaciones para enumeraciones. Se proporcionaron.
LWG 2543 C++11 Puede que hash no sea amigable con SFINAE. Se hizo amigable con SFINAE mediante especializaciones deshabilitadas.
LWG 2817 C++11 Faltaba la especialización de nullptr_t. Se proporcionó.
close