はじめに
Qiitaにいくつか同じ内容の記事があるのは知っていますが, 満足できる内容ではなかったため書きました.
実装
ハッシュ値の結合はこちらを参考にしました(PDF注意).
#include <cstdint>
#include <unordered_map>
#include <functional>
#include <algorithm>
#include <string>
#include <iostream>
template<class T>
T hash_combine(T h0, T h1)
{}
template<>
uint32_t hash_combine<uint32_t>(uint32_t h0, uint32_t h1)
{
return h1 ^ (h0 + 0x9E3779B9U + (h1<<6) + (h1>>2));
}
template<>
uint64_t hash_combine<uint64_t>(uint64_t h0, uint64_t h1)
{
return h1 ^ (h0 + 0x9E3779B97F4A7C15ULL + (h1<<12) + (h1>>4));
}
struct pair_hash
{
using key_type = std::pair<uint32_t, std::string>;
using first_type = key_type::first_type;
using second_type = key_type::second_type;
size_t operator()(const key_type& key) const
{
size_t h0 = std::hash<first_type>{}(key.first);
size_t h1 = std::hash<second_type>{}(key.second);
return hash_combine(h0, h1);
}
};
int main(void)
{
using map_type = std::unordered_map<std::pair<uint32_t, std::string>, uint32_t, pair_hash>;
map_type map = {
{{0, "0"}, 0},
{{0, "1"}, 1},
{{1, "0"}, 2},
{{1, "1"}, 3},
};
for_each(map.begin(), map.end(), [](const map_type::value_type& x){ std::cout << "(" << x.first.first << "," << x.first.second << ")=>" << x.second << std::endl;});
return 0;
}
まとめ
std::to_string
で文字列にしてしまうと, 速度の問題以前にロケールの影響を受けます. 実用上ほとんどの場合問題になることはないとはいえ, 問題になるケースを踏んでしまうと発見が困難と予想されるため, 日曜プログラミング以外では使わない方がいいでしょう.