C++ 如何无序设置<;元组<;int,int>>;?

C++ 如何无序设置<;元组<;int,int>>;?,c++,boost,C++,Boost,我在构造一个无序集时遇到了一个奇怪的问题。我试过VC++8、gcc3.2、gcc4.3,结果都一样。我不知道代码有什么问题,以下是我的代码: #include <boost/unordered_set.hpp> #include <boost/tuple/tuple.hpp> // For unordered container, the declaration of operator== #include <boost/tuple/tuple_comparison

我在构造一个无序集时遇到了一个奇怪的问题。我试过VC++8、gcc3.2、gcc4.3,结果都一样。我不知道代码有什么问题,以下是我的代码:

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

编译器似乎看不到
哈希值(元组)
的定义。但是如果我将
元组
替换为其他数据类型,比如
struct F{inta,b;}
,它就可以工作了。真奇怪。我错过什么了吗?非常感谢。

将哈希函数放在名称空间boost中

#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) ;
}
#包括
#包括
#包括
使用名称空间std;
使用名称空间boost;
名称空间提升{
大小\u t哈希值(元组常量&t){
返回get(t)*10+get(t);
}
}
int main(){
无序集s;
元组t;
s、 插入(t);
}
史蒂文·渡边捷夫(Steven Watanabe)发布的更好的(对任何元组都更通用的解决方案):““[tuple][hash]哈希一个元组问题””

他的解决办法是:

#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);
   }
}
#包括
#包括
#包括
#包括
命名空间stlex
{
结构元组\u融合\u散列
{
类型定义大小\u t结果\u类型;
模板
#如果BOOST_版本>=104300
//注:Boost 1.43中的订单已更改
std::size_t运算符()(std::size_t nSeed,const t&crArg)const
#否则
std::size\u t运算符()(常数t&crArg,std::size\u t nSeed)常数
#恩迪夫
{
boost::hash_联合收割机(nSeed,crArg);
返回未授权的文件;
}
};
结构元组散列
{
模板
std::size\u t运算符()(常量元组和cr)常量
{
返回boost::fusion::fold(cr,0,tuple_fusion_hash());
}
};
}//结束命名空间stlex
名称空间提升
{
//----------------------------------------------------------------------------
//模板结构元组散列
//----------------------------------------------------------------------------
//描述:元组的哈希函数
//注意:由于ADL,必须在命名空间boost中声明
//----------------------------------------------------------------------------
模板
std::size\u t哈希值(const boost::tuple&cr)
{
const stlex::tuple_hash hsh;
返回hsh(cr);
}
}
中的这段代码为标准哈希类型(字符串、整数等)的所有c++0x元组提供了神奇的支持

这很像渡边捷文,但没有增压魔法和增压依赖

将代码放在头文件中并包含它,无序的元组集将开箱即用:

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

    };
}
#包括
名称空间标准{
名称空间
{
//来自boost的代码
//黄金比率的倒数有助于传播熵
//并处理重复项。
//参见迈克·西摩在boosthash combine中的神奇数字:
//     https://stackoverflow.com/questions/4948780
模板
内联无效哈希组合(标准::大小\u t和种子,t常量和v)
{
seed^=hash()(v)+0x9e3779b9+(seed2);
}
//从Matthieu M派生的递归模板代码。
模板
结构HashValueImpl
{
静态无效应用(大小和种子、元组常量和元组)
{
HashValueImpl::apply(种子,元组);
hash_combine(seed,get(tuple));
}
};
模板
结构HashValueImpl
{
静态无效应用(大小和种子、元组常量和元组)
{
hash_combine(seed,get(tuple));
}
};
}
模板
结构散列
{
尺寸
运算符()(std::tuple const&tt)const
{                                              
种子大小=0;
HashValueImpl::apply(seed,tt);
返回种子;
}                                              
};
}

您是否在代码中实际使用了
名称空间
?如果是,请取出。有关更多信息,请阅读此处:
#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;                                 
        }                                              

    };
}