c++ - que - handles wikipedia
¿Se puede usar std:: hash para hash punteros de función? (3)
Encontré lo siguiente:
17.6.3.4 Requisitos de hash
Un tipo H cumple con los requisitos de hash si:
- es un tipo de objeto de función (20.8)
[...]
Y luego, la referencia 20.8 establece:
Un tipo de objeto de función es un tipo de objeto (3.9) que puede ser el tipo de expresión-postfix en una llamada de función (5.2.2, 13.3.1.1) .228 Un objeto de función es un objeto de un tipo de objeto de función. En los lugares donde uno esperaría pasar un puntero a una función a una plantilla algorítmica (Cláusula 25), la interfaz se especifica para aceptar un objeto de función. Esto no solo hace que las plantillas algorítmicas funcionen con punteros a funciones, sino que también les permite trabajar con objetos de funciones arbitrarias.
Es como que lo dice al revés ... pero la declaración no solo hace que las plantillas algorítmicas funcionen con punteros a funciones ... parece apropiado para su pregunta.
¿Se puede usar el tipo std::hash
C ++ 11 para los punteros de función hash? Hay una especialización parcial hash
definida como
template <typename T> struct hash<T*>;
pero como los punteros de función son diferentes de otros tipos de punteros en C ++ (por ejemplo, no se pueden convertir en void*
), no estoy seguro de que sea seguro usarlos para tipos como int(*)()
o void(*)(int, int)
.
¿Está esto permitido? ¿Hay alguna redacción específica en la nueva especificación ISO que respalde o refute esto?
¡Gracias!
Es realmente interesante ... Me topé con esta pregunta mientras utilizaba MSVC ++. Lo que estoy tratando de hacer es:
static std::unordered_map<Fun, std::string> FunctionMap()
{
static std::unordered_map<Fun, std::string> map;
return map;
}
Con un tipo de puntero a función Fun.
Durante la compilación, obtengo el siguiente error:
error C2338: The C++ Standard doesn''t provide a hash for this type.
....
_Kty=int (__thiscall Testje::* )(int,int)
En un intento anterior, intenté lanzar el puntero a la función void*
, que no está permitido y no se compila (consulte: https://isocpp.org/wiki/faq/pointers-to-members#cant-cvt-memfnptr-to-voidptr para más detalles). La razón es que un vacío * es un puntero de datos, mientras que un puntero de función es un puntero de código.
Mi conclusión hasta ahora es que no está permitido y no se compilará en MSVC ++.
Gran pregunta No conozco la respuesta con seguridad, y me complace remitirlo a cualquier persona que tenga un mejor conocimiento que yo, pero mi opinión es que aunque los punteros de función no son lo mismo que los punteros de datos, son punteros, no obstante, std::hash<T*>
debe aplicarse especialización parcial.
Para lo que vale, lo siguiente compila sin advertencias, incluso con -pendantic
en g ++ 4.8.1 y clang 3.3, y funciona como se esperaba:
#include <functional>
#include <iostream>
void func1(int) {}
void func2(int) {}
int main()
{
typedef void (*func_type) (int);
std::hash<func_type> hash;
std::cout << hash(func1) << std::endl;
std::cout << hash(func2) << std::endl;
}
Estaría realmente interesado si alguien tiene alguna referencia al estándar para respaldar esto.