¿Cómo hacer hash y comparar una función de puntero a miembro?

¿Cómo puedo i hash (std :: tr1 :: hash o boost :: hash) una función puntero-a-miembro de c ++?

Ejemplo:

Tengo varios bool (Class :: * functionPointer) () (no estáticos) que apuntan a varios métodos diferentes de la clase Class y necesito hash esos puntero-a-miembro-función.

¿Cómo puedo hacer eso?

Además, ¿cómo puedo comparar (std :: less) los punteros de funciones de miembros para que pueda almacenarlos en un conjunto estándar?

Todos los objetos C ++, incluidos los punteros a funciones miembro, se representan en la memoria como una matriz de caracteres. Entonces podrías probar:

bool (Class::*fn_ptr)() = &Class::whatever; const char *ptrptr = static_cast(static_cast(&fn_ptr)); 

Ahora trate ptrptr como apuntando a una matriz de bytes (sizeof(bool (Class::*)())) , y hash o compare esos bytes. Puede usar unsigned char lugar de char si lo prefiere.

Esto no garantiza falsos positivos: en C ++ 03, los punteros a las funciones miembro son POD, lo que significa, entre otras cosas, que se pueden copiar utilizando memcpy. Esto implica que si tienen los mismos valores de byte por byte, entonces son los mismos.

El problema es que la representación de almacenamiento de los punteros de función miembro podría incluir bits que no participan en el valor, por lo que no necesariamente serán los mismos para diferentes punteros a la misma función de miembro. O el comstackdor podría, por alguna razón oscura, tener más de una forma de señalar la misma función de la misma clase, que no son iguales en bytes. De cualquier manera, puede obtener falsos negativos. Deberá analizar cómo los punteros de función de miembro realmente funcionan en su implementación. Debe implementar operator== para punteros de función de miembro de alguna manera, y si puede averiguar cómo, entonces probablemente pueda averiguar una orden y una función hash.

Eso es potencialmente difícil: los punteros de función de los miembros son incómodos, y es probable que el almacenamiento incluya diferentes cantidades de “espacio de holgura” no participante según el tipo de función señalada (virtual, heredada). Por lo tanto, probablemente deba interactuar bastante significativamente con los detalles de implementación de su comstackdor. Este artículo podría ayudarlo a comenzar: http://www.codeproject.com/KB/cpp/ FastDelegate.aspx

Una alternativa más limpia podría ser hacer una búsqueda lineal a través de una matriz para “canonicalizar” todos los punteros a su función, luego comparar y hacer hash según la posición de la instancia “canónica” de ese puntero de función en la matriz. Depende de cuáles son sus requisitos de rendimiento. E incluso si hay requisitos, ¿tiene la clase (y sus clases derivadas) tantas funciones que la búsqueda lineal llevará tanto tiempo?

 typedef bool (Class::*func)(); vector canon; size_t getIndexOf(func fn_ptr) { vector::iterator it = find(canon.begin(), canon.end(), fn_ptr); if (it != canon.end()) return it - canon.begin(); canon.push_back(func); return canon.size() - 1; } 

No pude lanzar el puntero (en el comstackdor de Microsoft 2010) como se describe en la respuesta anterior, pero esto funciona para mí:

 static string fmptostr(int atype::*opt) { char buf[sizeof(opt)]; memcpy(&buf,&opt,sizeof(opt)); return string(buf,sizeof(opt)); } 

Acerca de la identidad bit a bit del puntero, puede ser en modo bit, por lo que parece que se utilizan los modificadores del comstackdor. Al menos esto es cierto para el comstackdor de Microsoft Ej. Usando #pragma pointers_to_members y un switch … / vmg