boost::asio::ip::tcp::endpoint 的无序集 - 试图引用已删除的函数

unorderered set for boost::asio::ip::tcp::endpoint - attempting to reference a deleted function

我正在存储唯一的端点,但收到构造函数的编译错误

std::unordered_set<boost::asio::ip::tcp::endpoint> addresses;

错误

Error C2280  'std::hash<_Kty>::hash(const std::hash<_Kty> &)': attempting to reference a deleted function
        with
        [
            _Kty=tcp_endpoint
        ]   
C:\Program Files (x86)\Microsoft Visual Studio19\Professional\VC\Tools\MSVC.22.27905\include\unordered_set

我试图通过如下定义比较器来做到这一点,但我得到 运行 时间断言错误,说比较函数无效。

using tcp = boost::asio::ip::tcp;       // from <boost/asio/ip/tcp.hpp>
struct comp {
    bool operator()(const tcp::endpoint& l, const tcp::endpoint& r) const
    {
        if (l.address().to_string() != r.address().to_string()) {
            return true;
        }
        else {
            return false;
        }
    }
};
std::set<tcp::endpoint,comp> getSet() {
    std::set<tcp::endpoint, comp> setOfStrs;

    auto const address = net::ip::make_address("192.168.0.1");
    auto const port = 9090;
    tcp::endpoint ep{ address, port };

    auto const address2 = net::ip::make_address("192.168.0.2");
    auto const port2 = 9090;
    tcp::endpoint ep2{ address2, port2 };
    setOfStrs.insert(ep);
    setOfStrs.insert(ep2);

    setOfStrs.insert(ep2);

    return setOfStrs;
}

请告诉我如何解决这个问题。这可能是一件小事,但我是 C++ 的新手,所以不能很快弄明白。

在其他语言中,可以使用 Hashset 并调用 add 来添加一个对象。 我正在使用矢量,但有重复项。

一个std::unordered_sethttps://en.cppreference.com/w/cpp/container/unordered_set)要求你提供的类型有两个属性:

  • 一个哈希函数,用于确定必须在其中存储值的桶
  • Aoperator==,看两个值是否相同,以解决冲突

我可以从: https://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/ip__tcp/endpoint.html

operator==可用,但哈希函数不行。所以你应该自己写一个。鉴于此,你也可以使用 std::set 我想你可以这样直接使用它:

std::set<tcp::endpoint>

因为 std::set 只需要一种方法来比较两个元素 (https://en.cppreference.com/w/cpp/container/set) 而 endpointoperator<.

或者,您应该考虑编写自己的散列函数,最有可能是您自己的比较器以适合您的用例,我看到您尝试使用 addressto_string() 的输出在你的比较器中。 也许你可以散列 to_string() 的输出来实现散列函数,并使用字符串比较(在 to_string() 的输出上)作为比较函数。