[英]Why no default hash for C++ POD structs?
我想在地圖中使用POD結構作為哈希鍵,例如
struct A { int x; int y; };
std::unordered_map<A, int> my_map;
但是我不能這樣做,因為沒有哈希函數可以自動生成這樣的結構。
從文檔中可以看出,您的案例可能是:
#include<functional>
#include<unordered_map>
struct A { int x; int y; };
namespace std
{
template<> struct hash<A>
{
using argument_type = A;
using result_type = std::size_t;
result_type operator()(argument_type const& a) const
{
result_type const h1 ( std::hash<int>()(a.x) );
result_type const h2 ( std::hash<int>()(a.y) );
return h1 ^ (h2 << 1);
}
};
}
int main() {
std::unordered_map<A, int> my_map;
}
編譯器不允許生成這樣的專門化,因為標准沒有定義類似的東西(如評論中已經提到的)。
有一種為POD生成哈希的方法,就像舊的c
風格一樣。 僅適用於結構外部沒有任何鏈接數據的真實POD。 代碼中沒有檢查此要求,因此只有在您知道並且可以保證這一點時才使用它。 必須初始化所有字段(例如,默認構造函數,如此A(),B()等)。
#pragma pack(push) /* push current alignment to stack */
#pragma pack(1) /* set alignment to 1 byte boundary */
struct A { int x; int y; };
struct B { int x; char ch[8] };
#pragma pack(pop) /* restore original alignment from stack */
struct C { int x __attribute__((packed)); };
template<class T> class PodHash;
template<>
class PodHash<A> {
public:
size_t operator()(const A &a) const
{
// it is possible to write hash func here char by char without using std::string
const std::string str =
std::string( reinterpret_cast<const std::string::value_type*>( &a ), sizeof(A) );
return std::hash<std::string>()( str );
}
};
std::unordered_map< A, int, PodHash<A> > m_mapMyMapA;
std::unordered_map< B, int, PodHash<B> > m_mapMyMapB;
UPD:必須在數據打包部分中定義數據結構,其值為一個字節或具有pack屬性以防止填充字節。
UPD:但我需要警告,替換deafult包裝會使某些字段的數據加載/存儲到某些字段的速度很慢,以防止需要按照與您(或最常用)體系結構相對應的粒度排列結構數據字段。
我建議您可以自行添加其他未使用的字段,而不是用於數據結構中的排列字段,以獲得最佳的內存加載/存儲性能。 例:
struct A
{
char x; // 1 byte
char padding1[3]; // 3 byte for the following 'int'
int y; // 4 bytes - largest structure member
short z; // 2 byte
char padding2[2]; // 2 bytes to make total size of the structure 12 bytes
};
#pragma pack
至少支持:
更靈活的方法是聲明比較類並將其用作std::unordered_map
模板參數。
struct A { int x; int y; };
emplate<class T> class MyHash;
template<>
class MyHash<A> {
public:
size_t operator()(const A &a) const
{
result_type const h1 ( std::hash<int>()(a.x) );
result_type const h2 ( std::hash<int>()(a.y) );
return h1 ^ (h2 << 1);
}
};
std::unordered_map<CString,CString,MyHash> m_mapMyMap;
您可能需要另一個Hash用於相同的對象。 靈活性出現在這樣的代碼中:
std::unordered_map<CString,CString, *MyAnotherHas* > m_mapMyMap;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.