我想说
std::hash_map<GUID, int> foo;
我相信这样做我必须创建一个
bool operator < (const GUID &guid1, const GUID &guid2);
std::size_t hash_value(GUID const &b);
比较GUID的正确方法是什么? (memcmp?) - 生成哈希的正确方法是什么?
如果有人能够充实这两个功能,那就太棒了,我已经阅读了几十个帖子,这些帖子做了所有事情,但却给出了最后的线索: - )答案 0 :(得分:3)
来自documentation似乎:
typedef struct _GUID {
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[8];
} GUID;
可能有几种可能性
建立自己的
为了比较我会逐项推送
bool operator < (const GUID &guid1, const GUID &guid2) {
if(guid1.Data1!=guid2.Data1) {
return guid1.Data1 < guid2.Data1;
}
if(guid1.Data2!=guid2.Data2) {
return guid1.Data2 < guid2.Data2;
}
if(guid1.Data3!=guid2.Data3) {
return guid1.Data3 < guid2.Data3;
}
for(int i=0;i<8;i++) {
if(guid1.Data4[i]!=guid2.Data4[i]) {
return guid1.Data4[i] < guid2.Data4[i];
}
}
return false;
}
对于散列...我会选择UuidHash函数(请注意,GUID是UUID的一种形式,如UUID definition所示)
返回字符串
使用StringFromCLSID从GUID获取字符串...一旦你有了字符串,就拥有了所有的操作符。
......这可能更贵。
答案 1 :(得分:3)
C ++库中没有std :: hash_map,stdext :: hash_map是一个过时的类(参见http://msdn.microsoft.com/en-us/en-en/library/0d462wfh.aspx)。
在std :: unordered_map中使用GUID:
#include <climits>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <unordered_map>
// Adopted from http://msdn.microsoft.com/en-us/library/windows/desktop/aa373931%28v=vs.85%29.aspx
typedef struct _GUID
{
std::uint32_t Data1;
std::uint16_t Data2;
std::uint16_t Data3;
std::uint8_t Data4[8];
} GUID;
// Ensure it has 128 bits
static_assert(sizeof(_GUID) == 128/CHAR_BIT, "GUID");
// The compare operator is required by std::unordered_map
inline bool operator == (const GUID& a, const GUID& b) {
return std::memcmp(&a, &b, sizeof(GUID)) == 0;
}
// A wrapper to create a GUID
inline GUID make_guid() {
// Should return the value of some library function.
return GUID();
}
// Specialize std::hash
namespace std {
template<> struct hash<GUID>
{
size_t operator()(const GUID& guid) const noexcept {
const std::uint64_t* p = reinterpret_cast<const std::uint64_t*>(&guid);
std::hash<std::uint64_t> hash;
return hash(p[0]) ^ hash(p[1]);
}
};
}
// Usage
int main(void) {
typedef std::unordered_map<GUID, int> map_type;
map_type m;
m.insert(map_type::value_type(make_guid(), 0));
m.insert(map_type::value_type(make_guid(), 1));
m.insert(map_type::value_type(make_guid(), 2));
}
答案 2 :(得分:3)
由于GUID只是POD,应该可以这样做:
namespace std
{
template<> struct hash<GUID> : public std::_Bitwise_hash<GUID>
{
};
}
答案 3 :(得分:0)
你的GUID是什么类型的?考虑下面这段代码:
struct MyCompare : binary_function<SomeClass, SomeClass, bool>
{
//constructor
MyCompare(int (SomeClass::*p)() const, int (SomeClass::*p2)() const) : pointer(p), pointer2(p2) {}
//comparison functor
bool operator < (SomeClass const& left, SomeClass const& right)
{
if ((left.*pointer)() != (right.*pointer)())
{
return less<int>()((left.*pointer)(), (right.*pointer)());
}
else
{
return less<int>()((left.*pointer2)(), (right.*pointer2)());
}
}
private:
int (SomeClass::*pointer)() const;
int (SomeClass::*pointer2)() const;
};
这是针对int类型的2个字段的复合键。排序第一个指针然后稳定排序第二个指针代码可能不会先尝试,但你明白了。
答案 4 :(得分:0)
对于Windows实现,我只需前往::UuidHash()。因此哈希函数将变为如此:
#include <rpc.h>
namespace std
{
template<> struct hash<GUID>
{
size_t operator()(const GUID &Value) const
{
RPC_STATUS status = RPC_S_OK;
return ::UuidHash(&const_cast<GUID&>(Value), &status);
}
};
}
说明:
答案 5 :(得分:-1)
首先,鉴于GUID是一般概念,您应该指定您正在谈论的GUID类。我会猜测它是this Microsoft Windows one,因为您标记了visual-c++
....
快速搜索&#34;哈希GUID&#34;显示Microsoft提供了推荐的哈希,请参阅here。听起来它有严重的缺陷,描述here。
如果由于某种原因您无法或不想使用它,请考虑数据成员:
typedef struct _GUID {
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[8];
} GUID;
这些非C ++ - 标准类型记录在案here。 你可以得到一个合理的32位散列,例如:
DWORD hash(const GUID& g)
{
return std::hash(g.Data1 ^
((g.Data2 << 16) | g.Data3) ^
*(DWORD*)(g.Data4) ^
*(DWORD*)(g.Data4 + 4);
}
要理解这一点 - 它有效地采用了这样的字段:
[16 bits here] [16 bits here]
g.Data1=0101100101010010:1001010101001010
g.Data2=1011110101001001 1011101010101010=g.Data3
g.Data4[0..3]=1010111010101010:0011101001000101
g.Data3[4..7]=1101111010100100:1010100011010110
hash=1001010000010101:1011110101110001
从上到下,它将所有比特放在一起,所以如果上面的1比特奇数,则上面的最后一个哈希线为1。如果你想要一个更强的哈希,你可以通过例如比特左右移位一个贡献值。 3-16位,两者兼顾,或使用hash_combine()
函数(google it!)。
对于哈希映射,您不需要operator<
(您只需要一个用于排序的二叉树 - 即std::map
),但确实需要能够比较等价...即operator==
。您确实可以使用memcpy进行比较 - 给定字段大小和顺序,它清楚结构不需要填充,因此所有位对于比较都是有意义的。您必须使用memcmp
,分别比较每个字符,或使用更多类型转换,因此我只使用单个memcmp
运行....