C++ C++;:在无序映射中使用一对(cpp_int,int)整数作为密钥(其中cpp_int是boost多精度整数)

C++ C++;:在无序映射中使用一对(cpp_int,int)整数作为密钥(其中cpp_int是boost多精度整数),c++,dictionary,boost,C++,Dictionary,Boost,对于我的无序映射,我想使用(cpp_int,int)的键对,其中cpp_int是整数: #include <boost/multiprecision/cpp_int.hpp> #include <unordered_map> using boost::multiprecision::cpp_int; std::unordered_map<std::pair<cpp_int, int>, double> myMap #包括 #包括 使用boos

对于我的无序映射,我想使用
(cpp_int,int)
的键对,其中
cpp_int
是整数:

#include <boost/multiprecision/cpp_int.hpp>
#include <unordered_map>

using boost::multiprecision::cpp_int;

std::unordered_map<std::pair<cpp_int, int>, double> myMap
#包括
#包括
使用boost::multiprecision::cpp_int;
std::无序映射myMap
在这个网站上搜索时,我发现了许多建议,可以使用自定义哈希函数作为
std::pair
的密钥,但我找不到如何处理
std::pair

更新:为了澄清这一点,我尝试了在web上找到的哈希函数(用于(int,int):

#包括
#包括
使用boost::multiprecision::cpp_int;
typedef std::pair MyPair;
结构MyHash{
公众:
size_t运算符()(MyPair x)const throw(){
尺寸h=x.first*1+x.second*100000;
返回h;
}
};
空函数()
{
std::无序映射M;
}
这不会编译:

error: cannot convert ‘boost::enable_if_c<true, boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_add, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<> >, void, void, void>, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, int, void, void, void>, int, void> >::type {aka boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_add, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<> >, void, void, void>, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, int, void, void, void>, int, void>}’ to ‘size_t {aka long unsigned int}’ in initialization
              size_t h = x.first * 1 + x.second * 100000;
                                                  ^
错误:无法在初始化中将'boost::enable_if_c::type{aka boost::multiprecision::detail::expression}'转换为'size_t{aka long unsigned int}'
尺寸h=x.first*1+x.second*100000;
^
我的问题是:如何使用成对的(cpp\u int,int)作为无序映射中的键?

提前非常感谢

更新2: 感谢@sehe为我指出(他在其中为cpp_int提供了一个散列函数)。结合(它显示了如何将两个散列函数组合成一对),我想出了以下解决方案(它编译得很好,我需要对我的问题进行测试,看看它是否有效):

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用boost::multiprecision::cpp_int;
typedef std::pair MyPair;
名称空间mp_散列{
名称空间io=boost::iostreams;
结构哈希_接收器{
哈希接收器(大小和种子参考):\u ptr(和种子参考){}
typedef char_类型;
类型定义io::接收器标签类别;
std::streamsize写入(常量字符*s,std::streamsize n){
boost::hash_combine(*_ptr,boost::hash_range(s,s+n));
返回n;
}
私人:
尺寸*;
};
模板结构哈希\u impl{
大小\u t运算符()(t常量和v)常量{
使用名称空间boost;
种子大小=0;
{
iostreams::流操作系统(种子);
归档::二进制oarchive oa(操作系统,归档::无头|归档::无编解码器);

oa是的,您使用了我之前提供的多精度散列,并为
std::pair
添加了散列。我不喜欢手工操作散列组合(良好的通用散列组合并不简单)

所以我会对
boost::hash\u combine
做同样的事情:

template <typename K, typename V>
struct hash<std::pair<K, V> > 
{
    size_t operator()(std::pair<K, V> const& pair) const {
        size_t seed = std::hash<K>{}(pair.first);
        boost::hash_combine(seed, pair.second);
        return seed;
    }
};
模板
结构散列
{
size_t运算符()(std::pair const和pair)const{
size\u t seed=std::hash{}(pair.first);
boost::hash_combine(种子,配对。秒);
返回种子;
}
};

#include <iostream>
#include <iomanip>

#include <boost/archive/binary_oarchive.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_int/serialize.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/stream.hpp>

#include <boost/functional/hash.hpp>

namespace mp_hashing {
    namespace io = boost::iostreams;

    struct hash_sink {
        hash_sink(size_t& seed_ref) : _ptr(&seed_ref) {}

        typedef char         char_type;
        typedef io::sink_tag category;

        std::streamsize write(const char* s, std::streamsize n) {
            boost::hash_combine(*_ptr, boost::hash_range(s, s+n));
            return n;
        }
      private:
        size_t* _ptr;
    };

    template <typename T> struct hash_impl {
        size_t operator()(T const& v) const {
            using namespace boost;
            size_t seed = 0;
            {
                iostreams::stream<hash_sink> os(seed);
                archive::binary_oarchive oa(os, archive::no_header | archive::no_codecvt);
                oa << v;
            }
            return seed;
        }
    };
}

#include <unordered_map>
#include <boost/unordered_map.hpp>

namespace std {
    template <typename backend> 
    struct hash<boost::multiprecision::number<backend> > 
        : mp_hashing::hash_impl<boost::multiprecision::number<backend> > 
    {};

    template <typename K, typename V>
    struct hash<std::pair<K, V> > 
    {
        size_t operator()(std::pair<K, V> const& pair) const {
            size_t seed = std::hash<K>{}(pair.first);
            boost::hash_combine(seed, pair.second);
            return seed;
        }
    };
}

int main() {
    using boost::multiprecision::cpp_int;

    std::unordered_map<std::pair<cpp_int, int>, int>  m {
        { { cpp_int(1) << 111, -1 }, 1 },
        { { cpp_int(2) << 222, -2 }, 2 },
        { { cpp_int(3) << 333, -3 }, 3 },
    };

    for (auto& p : m)
        std::cout << p.first.first << " -> " << p.second << "\n";
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
名称空间mp_散列{
名称空间io=boost::iostreams;
结构哈希_接收器{
哈希接收器(大小和种子参考):\u ptr(和种子参考){}
typedef char_类型;
类型定义io::接收器标签类别;
std::streamsize写入(常量字符*s,std::streamsize n){
boost::hash_combine(*_ptr,boost::hash_range(s,s+n));
返回n;
}
私人:
尺寸*;
};
模板结构哈希\u impl{
大小\u t运算符()(t常量和v)常量{
使用名称空间boost;
种子大小=0;
{
iostreams::流操作系统(种子);
归档::二进制oarchive oa(操作系统,归档::无头|归档::无编解码器);

oa你有cpp_int的哈希值吗?你知道如何组合哈希值吗?如果两者都有,你有什么问题?如果没有,你尝试了什么?@Ron我已经更新了问题。很抱歉,它不是很清楚。@Yakk我对这些东西很陌生,我还没有在网上找到我需要的,所以…我没有cpp_int的哈希值。不过你现在有了,@Khue(下一次,只需搜索:)。下面是MSVC使用
unordered_map
:/cc@YakkYup的现场演示,正如我所写的:“主要用于演示目的,即工作正常,但过于简单”,因为您正在使用boost。
boost.hash\u组合
或者更直接地说,
boost::hash\u值(std::pair)
是一个不错的选择。请注意,
boost::hash_value
已经为
std::pair
@BaummitAugen Cool提供了一个重载-我想我记得这一点,但今天早些时候不知怎的绊倒了过去。
template <typename K, typename V>
struct hash<std::pair<K, V> > 
{
    size_t operator()(std::pair<K, V> const& pair) const {
        size_t seed = std::hash<K>{}(pair.first);
        boost::hash_combine(seed, pair.second);
        return seed;
    }
};
#include <iostream>
#include <iomanip>

#include <boost/archive/binary_oarchive.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_int/serialize.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/stream.hpp>

#include <boost/functional/hash.hpp>

namespace mp_hashing {
    namespace io = boost::iostreams;

    struct hash_sink {
        hash_sink(size_t& seed_ref) : _ptr(&seed_ref) {}

        typedef char         char_type;
        typedef io::sink_tag category;

        std::streamsize write(const char* s, std::streamsize n) {
            boost::hash_combine(*_ptr, boost::hash_range(s, s+n));
            return n;
        }
      private:
        size_t* _ptr;
    };

    template <typename T> struct hash_impl {
        size_t operator()(T const& v) const {
            using namespace boost;
            size_t seed = 0;
            {
                iostreams::stream<hash_sink> os(seed);
                archive::binary_oarchive oa(os, archive::no_header | archive::no_codecvt);
                oa << v;
            }
            return seed;
        }
    };
}

#include <unordered_map>
#include <boost/unordered_map.hpp>

namespace std {
    template <typename backend> 
    struct hash<boost::multiprecision::number<backend> > 
        : mp_hashing::hash_impl<boost::multiprecision::number<backend> > 
    {};

    template <typename K, typename V>
    struct hash<std::pair<K, V> > 
    {
        size_t operator()(std::pair<K, V> const& pair) const {
            size_t seed = std::hash<K>{}(pair.first);
            boost::hash_combine(seed, pair.second);
            return seed;
        }
    };
}

int main() {
    using boost::multiprecision::cpp_int;

    std::unordered_map<std::pair<cpp_int, int>, int>  m {
        { { cpp_int(1) << 111, -1 }, 1 },
        { { cpp_int(2) << 222, -2 }, 2 },
        { { cpp_int(3) << 333, -3 }, 3 },
    };

    for (auto& p : m)
        std::cout << p.first.first << " -> " << p.second << "\n";
}