9
votes

Comment faire une hache et comparer une fonction de pointeur à membre?

Comment puis-je hachage (std :: tr1 :: hachage ou boost ou boost :: hachage) une fonction de pointe-à-membre C ++?

Exemple:

J'ai plusieurs Bool (Classe :: * Fonctionpoinger) () (non statique) qui pointez sur plusieurs méthodes différentes de la classe de classe et j'ai besoin de hachage de la fonction pointeur-à-membre.

Comment puis-je faire ça?

Aussi comment puis-je comparer (std :: moins) ces pointeurs de la fonction membre pour que je puisse les stocker dans un std :: set?


5 commentaires

Il n'y a normalement aucune raison de hacher un pointeur, car il pointe directement à la chose que vous souhaitez accéder. Veuillez fournir du code qui illustre ce que vous demandez.


Quand diriez-vous qu'un pointeur de fonction est «moins» qu'un autre?


@bojan: Si le seul but de la comparaison est de les stocker dans une liste triée, tout commandement déterministe fera. Par exemple la valeur binaire.


J'ai une classe qui a un pointeur de fonction membre en tant que variable membre. J'ai besoin de stocker cette classe dans un STD :: Set et dans une STD :: Hash_Shset, donc il a besoin d'un hachage et d'un STD :: moins sur ce pointeur de fonction membre.


Aurez-vous des cas de votre classe identiques dans chaque domaine, à l'exception du pointeur de la fonction membre? Sinon, vous n'avez pas besoin de l'inclure dans le hachage / comparaison, ce qui évite parfaitement le problème.


3 Réponses :


13
votes

Tous les objets C ++, y compris les pointeurs aux fonctions des membres, sont représentés en mémoire comme une éventail de caractères. Donc, vous pouvez essayer: xxx

Traitement maintenant PTRPTR comme indiquant un tableau de (Tailleof (BOOL (Classe :: *) ())) / code> octets et hachage ou comparent ces octets. Vous pouvez utiliser non signé char au lieu de char si vous préférez.

Ceci garantit non de faux positifs - en C ++ 03, les pointeurs des fonctions membres sont Pod, ce qui signifie entre autres choses qu'ils peuvent être copiés en utilisant memcpy. Cela implique que si vous avez les mêmes valeurs d'octet-octet, ils sont les mêmes.

Le problème est que la représentation de la fonction de stockage des points de fonction des membres pourrait inclure des bits qui ne participent pas à la valeur. Ils ne seraient pas nécessairement les mêmes pour différents pointeurs à la même fonction membre. Ou le compilateur peut, pour une raison obscure, avoir plus d'une façon de pointer vers la même fonction de la même classe, qui ne sont pas d'un octet-sage égal. De toute façon, vous pouvez obtenir de faux négatifs. Vous devrez examiner comment les pointeurs de la fonction membre fonctionnent réellement sur votre mise en œuvre. Il doit implémenter opérateur == pour les pointeurs de fonction de membre en quelque sorte, et si vous pouvez découvrir comment vous pouvez probablement comprendre une commande et une fonction de hachage.

C'est potentiellement difficile: Les pointeurs de la fonction de membre sont maladroits et le stockage est susceptible d'inclure différentes quantités de "espace mou" non participant en fonction de quel type de fonction est pointé vers (virtuel, hérité). Donc, vous devrez probablement interagir de manière assez significative avec les détails de la mise en œuvre de votre compilateur. Cet article pourrait vous aider à vous aider à démarrer: http://www.codeproject.com/kb/cppp /Fastdelegate.aspx

Une alternative plus propre peut être de faire une recherche linéaire via un tableau afin de "Canonicaliser" tous vos pointeurs de fonction, puis de comparer et de hachage basé sur la position du " Instance canonique de ce pointeur de fonction dans votre tableau. Dépend quelles sont vos exigences de performance. Et même s'il existe des exigences, la classe (et ses classes dérivées) a-t-elle autant de fonctions que la recherche linéaire prendra cette longue? xxx


7 commentaires

Merci au char * fait le tour! Seulement dans mon compilateur, j'ai besoin d'un réinterpret_cast au lieu de static_cast.


Excellent traitement de certaines des questions épineuses, +1. Cela ne m'était pas venu que PMF1 == PMF2 n'implique pas nécessairement une identité binaire.


Un pointeur à la fonction membre peut contenir un rembourrage, qui serait ignoré lors de la comparaison pour l'égalité et peut prendre des valeurs aléatoires. Hache Tous les octets de rembourrage entraîneront l'échec de la fonction Hash.


@James: Je discute de cela, à partir de "Le problème, c'est que la représentation de stockage des pointes de la fonction membre pourrait inclure des bits qui ne participent pas à la valeur"


Tandis que l'idée de l'indice "canticalisé" est certainement intelligente (merci pour cette idée!), J'aimerais ajouter un avertissement: autant que je sache, il n'est pas possible d'accomplir l'égalité de comparer les pointeurs de membre à des fonctions virtuelles (par exemple, des fonctions. dans une interface / abc). Étant donné que le même "décalage" pourrait réellement résoudre différents implémentations, en fonction de l'instance réelle que vous liez le pointeur de membre. Ainsi, cette approche se décompose dans ce cas.


@Steve Votre implémentation (compilateur) peut être bâclée et permettre de telles comparaisons, mais la norme est explicite. Voir le § 5.10: "Si soit soit un pointeur sur une fonction de membre virtuel, le résultat n'est pas spécifié"


Voir C ++ 14 projet Page 120F (qui est au bas de la page 134 dans le PDF lié)



0
votes

Je ne pouvais pas lancer le pointeur (dans Microsoft Compiler 2010) comme décrit dans la réponse précédente, mais cela fonctionne pour moi: xxx

à propos de l'identité binaire du pointeur, il peut s'agir de la semble être utilisé si des commutateurs de compilation appropriés sont utilisés. Au moins cela est vrai pour Microsoft Compiler E.g en utilisant #pragma pointers_to_members et un commutateur ... / vmg


0 commentaires

0
votes

Si votre fonction de fonction membre est unique, ce qui est vrai dans la plupart des cas pour les abonnements basés sur Callback, vous pouvez utiliser la tique avec Type_index , quelle caractère unique est garanti par l'unicité du type (c.-à-d. Classe :: Méthode ) dans votre programme, et il convient de stocker dans Unorded_map , c'est-à-dire xxx

et l'exemple d'événement d'abonnement et d'incendie: xxx

donc, l'exemple ci-dessus donne Vous avez besoin d'un caractère de classe / de méthode, et si vous avez besoin d'un caractère d'objet / méthode, vous devez disposer d'une structure, qui fournit un hachage combiné, en supposant qu'il y a std :: hash et il y a déjà < Code> std :: hash pour un pointeur de fonction membre.


0 commentaires