2009-08-09 12 views
4

unordeed_set<tuple<int,int>>を作っているうちに、私は奇妙な問題に遭遇しました。私はVC++ 8、gcc3.2、gcc4.3を試してみましたが、すべて同じ結果があります。コンパイラがhash_value(tuple<int, int>)の定義を見ることができないようだunorderered_set <tuple <int,int>>の方法は?

1>c:\libs\boost_1_37_0\boost\functional\hash\extensions.hpp(72) : error C2665: 'boost::hash_value' : none of the 16 overloads could convert all the argument types 
1>  c:\libs\boost_1_37_0\boost\functional\hash\hash.hpp(33): could be 'size_t boost::hash_value(bool)' 
1>  c:\libs\boost_1_37_0\boost\functional\hash\hash.hpp(34): or  'size_t boost::hash_value(char)' 
1>  c:\libs\boost_1_37_0\boost\functional\hash\hash.hpp(35): or  'size_t boost::hash_value(unsigned char)' 
.... 

:ここ

#include <boost/unordered_set.hpp> 
#include <boost/tuple/tuple.hpp> 
// For unordered container, the declaration of operator== 
#include <boost/tuple/tuple_comparison.hpp> 

using namespace std ; 
using namespace boost ; 

// define of the hash_value funciton for tuple<int, int> 
size_t hash_value(tuple<int, int> const& t) { 
    return get<0>(t) * 10 + get<1>(t) ; 
} 

int main() { 
    unordered_set<tuple<int, int>> s ; 
    tuple<int, int> t ; 
    s.insert(t) ; 
} 

は、コンパイルエラーメッセージです:私は私のコードで、次のコードで間違って何見当がつかない。しかし、tuple<int, int>struct F{int a, b;}のような他のデータ型に置き換えても機能します。それは本当に奇妙です。私は何かが欠けていますか?どうもありがとうございました。

+2

あなたが実際にあなたのコード内でnamespace'を使用して '使用していますか?もしそうなら、それを取り出してください。 – GManNickG

答えて

6

名前空間の拡張にハッシュ関数を追加します。スティーブン・渡辺によって投稿

#include <boost/unordered_set.hpp> 
#include <boost/tuple/tuple.hpp> 
#include <boost/tuple/tuple_comparison.hpp> 

using namespace std; 
using namespace boost; 

namespace boost { 
    size_t hash_value(tuple<int, int> const & t) { 
     return get<0>(t) * 10 + get<1>(t) ; 
    } 
} 

int main() { 
    unordered_set< tuple<int, int> > s ; 
    tuple<int, int> t ; 
    s.insert(t) ; 
} 
+0

詳しくは、こちらをご覧ください:http://www.boost.org/doc/libs/1_37_0/doc/html/hash/custom.html – GManNickG

1

より良い(と任意のタプルのためのより一般的な解決策): http://lists.boost.org/boost-users/2008/06/37643.php

彼の解決策 ' "タプルの質問ハッシュ[組] [ハッシュ]"':

#include <boost/functional/hash.hpp> 
#include <boost/fusion/algorithm/iteration/fold.hpp> 
#include <boost/fusion/adapted/boost_tuple.hpp> 
#include <boost/tuple/tuple.hpp> 

namespace stlex 
{ 
    struct tuple_fusion_hash 
    { 
     typedef size_t result_type; 

     template <typename T> 
#if BOOST_VERSION >= 104300 
     //NOTE: order changed in Boost 1.43 
     std::size_t operator()(std::size_t nSeed, const T& crArg) const 
#else 
     std::size_t operator()(const T& crArg, std::size_t nSeed) const 
#endif 
     { 
     boost::hash_combine(nSeed, crArg); 
     return nSeed; 
     } 
    }; 


    struct tuple_hash 
    { 
     template <typename Tuple> 
     std::size_t operator()(const Tuple& cr) const 
     { 
     return boost::fusion::fold(cr, 0, tuple_fusion_hash()); 
     } 
    }; 

} //end namespace stlex 


namespace boost 
{ 
    //---------------------------------------------------------------------------- 
    // template struct tuple_hash 
    //---------------------------------------------------------------------------- 
    // Description: hash function for tuples 
    // Note  : must be declared in namespace boost due to ADL 
    //---------------------------------------------------------------------------- 
    template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9> 
    std::size_t hash_value(const boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& cr) 
    { 
     const stlex::tuple_hash hsh; 
     return hsh(cr); 
    } 
} 
0

Generic hash for tuples in unordered_map/unordered_setのこのコードは、標準的なハッシュ可能型(文字列、intなど)のすべてのC++ 0xタプルに対して魔法のサポートを提供します。

これはSteven Watanabeに非常によく似ていますが、ブーストマジックはアンパックされ、ブースト依存関係はありません。

ヘッダファイルにコードを入れて、それを含めるとタプルの順不同のセットは、箱から出して動作します:

#include <tuple> 
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: 
     //  https://stackoverflow.com/questions/4948780 

     template <class T> 
     inline void hash_combine(std::size_t& seed, T const& v) 
     { 
      seed ^= 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, get<Index>(tuple)); 
      } 
     }; 

     template <class Tuple> 
     struct HashValueImpl<Tuple,0> 
     { 
      static void apply(size_t& seed, Tuple const& tuple) 
      { 
      hash_combine(seed, get<0>(tuple)); 
      } 
     }; 
    } 

    template <typename ... TT> 
    struct hash<std::tuple<TT...>> 
    { 
     size_t 
     operator()(std::tuple<TT...> const& tt) const 
     {            
      size_t seed = 0;        
      HashValueImpl<std::tuple<TT...> >::apply(seed, tt);  
      return seed;         
     }            

    }; 
} 
関連する問題