如何散列和比较指向成员函数的指针?
我如何散列(std::tr1::hash 或 boost::hash)c++ 成员函数指针?
示例:
我有几个 bool (Class::*functionPointer)() (非静态)指向类 Class 的几个不同方法,我需要对这些指向成员函数的指针进行哈希处理。
我怎样才能做到这一点?
另外,我如何比较(std::less)这些成员函数指针,以便将它们存储在 std::set 中?
How can i hash (std::tr1::hash or boost::hash) a c++ pointer-to-member-function?
Example:
I have several bool (Class::*functionPointer)() (not static) that point to several diferent methods of the class Class and i need to hash those pointer-to-member-function.
How can i do that?
Also how can i compare (std::less) those member function pointers so i can store them in a std::set?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
所有 C++ 对象(包括指向成员函数的指针)在内存中都表示为字符数组。所以你可以尝试:
现在将 ptrptr 视为指向
(sizeof(bool (Class::*)()))
字节数组,并对这些字节进行散列或比较。如果您愿意,可以使用unsigned char
代替char
。这保证了没有误报 - 在 C++03 中,指向成员函数的指针是 POD,这意味着它们可以使用 memcpy 进行复制。这意味着如果逐字节值相同,则它们是相同的。
问题在于,成员函数指针的存储表示可能包括不参与该值的位,因此对于指向同一成员函数的不同指针,它们不一定相同。或者,由于某种模糊的原因,编译器可能有不止一种方法来指向同一类的相同函数,而这些方法在字节上并不相等。无论哪种方式,你都可能得到假阴性。您必须研究成员函数指针在您的实现中实际如何工作。它必须以某种方式实现成员函数指针的
operator==
,如果你能找出如何实现,那么你可能就能找出一个顺序和一个哈希函数。这可能很困难:成员函数指针很尴尬,并且根据指向的函数类型(虚拟的、继承的),存储可能包含不同数量的非参与“闲置空间”。因此,您可能必须与编译器的实现细节进行大量交互。本文可能会帮助您入门:http://www.codeproject.com/KB/cpp /FastDelegate.aspx
一个更简洁的替代方案可能是通过数组进行线性搜索,以便“规范化”所有函数指针,然后根据该函数指针的“规范”实例的位置进行比较和散列在你的数组中。取决于你的性能要求是什么。而且即使有要求,类(及其派生类)是否有如此多的函数以至于线性搜索需要那么长时间?
All C++ objects, including pointers to member functions, are represented in memory as an array of chars. So you could try:
Now treat
ptrptr
as pointing to an array of(sizeof(bool (Class::*)()))
bytes, and hash or compare those bytes. You can useunsigned char
instead ofchar
if you prefer.This guarantees no false positives - in C++03, pointers to member functions are POD, which means among other things that they can be copied using memcpy. This implies that if have the same byte-for-byte values, then they are the same.
The problem is that the storage representation of member function pointers could include bits which do not participate in the value - so they will not necessarily be the same for different pointers to the same member function. Or the compiler might, for some obscure reason, have more than one way of pointing to the same function of the same class, which are not byte-wise equal. Either way you can get false negatives. You'll have to look into how member function pointers actually work on your implementation. It must implement
operator==
for member function pointers somehow, and if you can find out how then you can probably figure out an order and a hash function.That's potentially hard: member function pointers are awkward, and the storage is likely to include different amounts of non-participating "slack space" according to what kind of function is pointed to (virtual, inherited). So you'll probably have to interact quite significantly with your compiler's implementation details. This article might help get you started: http://www.codeproject.com/KB/cpp/FastDelegate.aspx
A cleaner alternative might be to do a linear search through an array in order to "canonicalise" all your function pointers, then compare and hash based on the position of the "canonical" instance of that function pointer in your array. Depends what your performance requirements are. And even if there are requirements, does the class (and its derived classes) have so many functions that the linear search will take that long?
我无法转换指针(在 Microsoft 编译器 2010 中),如前面的答案中所述,但这对我有用:
关于指针的按位标识,它可以是按位的,因此看起来是否使用了适当的编译器开关。至少对于微软编译器来说是这样的
使用#pragmapointers_to_members
和一个开关.../vmg
I could not cast the pointer (in Microsoft compiler 2010)as described in previous answer but this works for me:
About bitwise identity of the pointer, it can be bitwise so it seems if appropriate compiler switches are used. At least this is true for Microsoft compiler E.g
using #pragma pointers_to_members
and a switch.../vmg
如果您的成员函数指针是唯一的(在大多数情况下对于基于回调的订阅都是如此),那么您可以使用带有 type_index,其唯一性是通过程序中类型(即
Class::Method
)的唯一性来保证的,适合存储在unordered_map
,即订阅和触发事件示例:
因此,上面的示例为您提供了类/方法唯一性,如果您需要对象/方法唯一性,那么您应该有一个结构,它提供组合哈希,假设有
std::hash
并且已经有std::hash
用于成员函数指针。If your member function pointer is unique, which is true in most of cases for callback-based subscriptions, then you can use the tick with type_index, which uniqueness is guaranteed by uniqueness of type (i.e.
Class::Method
) in your program, and it is suitable to be stored inunordered_map
, i.e.And the subscription and fire event example:
So, example above gives you class/method uniqueness, and if you need object/method uniqueness, then you should have an struct, which provides combined hash, assuming that there is
std::hash<MyObject>
and there is alreadystd::hash<std::type_index>
for a member function pointer.