std::unowned_map がそのままタプル キーを簡単に操作できることを期待するかもしれません。ただし、以下に示すように、タプルのハッシュ関数を定義する必要があります。
template struct do_hash<tuple int>> { size_t operator()(std::tuple<int int> const& tt) const {...} };</int></tuple>
このプロセスは退屈になる可能性があり、可変引数テンプレートに頼らずに C 0x タプルに対して自動化するかどうかという問題が生じます。
次のアプローチでは、標準ハッシュ可能型を含むすべての C 0x タプルを unowned_map の一部にすることができ、追加の作業なしで unowned_set:
#include <tuple> namespace std { namespace { template <class t> inline void hash_combine(std::size_t& seed, T const& v) { // Modified from Boost seed ^= std::hash<t>()(v) + 0x9e3779b9 + (seed > 2); } // Recursive template for hashing tuples template <class tuple size_t index="std::tuple_size<Tuple">::value - 1> struct HashValueImpl { static void apply(size_t& seed, Tuple const& tuple) { HashValueImpl<tuple index>::apply(seed, tuple); hash_combine(seed, std::get<index>(tuple)); } }; template <class tuple> struct HashValueImpl<tuple> { static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get(tuple)); } }; } template <typename... tt> struct hash<:tuple>> { size_t operator()(std::tuple<tt...> const& tt) const { size_t seed = 0; HashValueImpl<:tuple>>::apply(seed, tt); return seed; } }; }</:tuple></tt...></:tuple></typename...></tuple></class></index></tuple></class></t></class></tuple>
関数を std 名前空間に配置すると、引数依存の名前検索 (ADL) 経由でアクセスできます。
std 名前空間内のオブジェクトを特殊化することは未定義の動作です。したがって、標準に準拠したソリューションの場合は、コードを別の名前空間に移動し、ADL の利便性を無視します。
namespace hash_tuple { // Forward non-tuple types to std::hash template <class tt> struct hash { size_t operator()(TT const& tt) const { return std::hash<tt>()(tt); } }; // Hash function combining values in a tuple template <class tuple size_t index="std::tuple_size<Tuple">::value - 1> struct HashValueImpl { static void apply(size_t& seed, Tuple const& tuple) { HashValueImpl<tuple index>::apply(seed, tuple); hash_combine(seed, std::get<index>(tuple)); } }; template <class tuple> struct HashValueImpl<tuple> { static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get(tuple)); } }; // Hash function for tuples template <typename... tt> struct hash<:tuple>> { size_t operator()(std::tuple<tt...> const& tt) const { size_t seed = 0; HashValueImpl<:tuple>>::apply(seed, tt); return seed; } }; } // namespace hash_tuple</:tuple></tt...></:tuple></typename...></tuple></class></index></tuple></class></tt></class>
hash_tuple 名前空間内でハッシュ実装を宣言して、すべての非タプル型を std に転送します。 :hash を変更し、std::hash の代わりに hash_tuple::hash を使用するように hash_combine を変更します。残りのコードを hash_tuple 名前空間内に配置します。
このソリューションを使用するには、ADL の利便性を放棄する次のコードを含める必要があります。
unordered_set<tuple int>, hash_tuple::hash<tuple int>>> test2;</tuple></tuple>
以上がカスタム ハッシュ関数を作成せずに、順序なしマップのキーとしてタプルを使用するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。