タプル キーを使用して順序なしマップとセットを作成するのは簡単ですが、タプルにカスタム ハッシュ関数を要求するのは面倒な場合があります。しかし、可変引数テンプレートを使用せずにこれを回避する方法はありますか?
C 0x では、以下のコードを使用してタプルの汎用ハッシュ関数を定義できます:
namespace std{ namespace { // Code from boost // Reciprocal of the golden ratio helps spread entropy // and handles duplicates. // See Mike Seymour in magic-numbers-in-boosthash-combine: // http://stackoverflow.com/questions/4948780 template <class T> inline void hash_combine(std::size_t& seed, T const& v) { seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); } // Recursive template code derived from Matthieu M. 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-1>::apply(seed, tuple); hash_combine(seed, std::get<Index>(tuple)); } }; template <class Tuple> struct HashValueImpl<Tuple,0> { static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get<0>(tuple)); } }; } template <typename ... TT> struct hash<std::tuple<TT...>> { size_t operator()(std::tuple<TT...>& tt) const { size_t seed = 0; HashValueImpl<std::tuple<TT...>>::apply(seed, tt); return seed; } }; }
標準への準拠を確保するには、次のように定義することをお勧めしますカスタム名前空間内のタプルのハッシュ関数により、ADL によって自動的に取得されなくなります。これには、最初にカスタム名前空間でハッシュ実装を宣言し、次に残りの汎用ハッシュ関数コードを含める必要があります。
namespace hash_tuple{ template <typename TT> struct hash { size_t operator()(TT const& tt) const { return std::hash<TT>()(tt); } }; } // ... Include the rest of the previous generic hash function code
このようにして、順序なしマップとセットは、ADL に依存せずにタプル キーで動作できます。そして基準は完全に遵守されています。
以上がC 0x で可変個引数テンプレートを使用せずに、タプルは順序付けされていないコンテナーで動作できますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。