2009-08-09 4 views
4

unordeed_set<tuple<int,int>>을 구성하는 동안 이상한 문제가 발생했습니다. 나는 VC++ 8, gcc3.2, gcc4.3을 시도했지만, 모두 같은 결과를 보였다.정렬 순서를 설정하는 방법 <tuple <int,int>>?

다음
#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) ; 
} 

이 컴파일 오류 메시지입니다 :

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)' 
.... 

그것은 hash_value(tuple<int, int>)의 정의를 볼 수없는 컴파일러를 보인다 나는 다음과 같은 코드에 문제가 있는지 아무 생각하는 것은 내 코드입니다. 하지만 tuple<int, int>struct F{int a, b;}과 같은 다른 데이터 형식으로 바꾸면 작동합니다. 정말 이상합니다. 나는 무엇이든 놓친다? 고맙습니다.

+2

:

는 헤더 파일에 코드를 넣어 상자 밖으로 작동합니다 그것과 튜플의 정렬되지 않은 세트를 포함? 그렇다면 꺼내십시오. – 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에서 표준 해시 가능 유형 (문자열, 정수 등)의 모든 C++ 0x 튜플에 대한 마법 지원을 제공합니다.

이것은 Steven Watanabe와 매우 비슷하지만 부스트 마법을 풀고 부스트 의존성을 사용하지 않았습니다. 실제로 코드에서 namespace`를 사용하여 '사용하고

#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;         
     }            

    }; 
} 
관련 문제