Search code examples
c++unordered-set

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


I am storing unique endpoints but getting compilation error for constructor

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

Error

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 Studio\2019\Professional\VC\Tools\MSVC\14.22.27905\include\unordered_set

I tried to do it by defining comparer as below but I get run time assertion error saying invalid compare function.

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

enter image description here

Please let me know how do I fix this. Its probably a small thing, but I am new to C++ so not able to figure it out soon.

In other languages one can use Hashset and call add to add an object. I was using vector but there were duplicates.


Solution

  • An std::unordered_set (https://en.cppreference.com/w/cpp/container/unordered_set) requires that the type you provide has two attributes:

    • A hash function to determine the bucket in which one has to store the value
    • A operator==, to see if two values are the same, in order to resolve collision

    I can see from: https://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/ip__tcp/endpoint.html

    That operator== is available, but not the hash function. So you should write one yourself. Given that, for you it is OK to use also std::set I think you can use it directly it this way:

    std::set<tcp::endpoint>
    

    because std::set needs only a way to compare two elements (https://en.cppreference.com/w/cpp/container/set) and endpoint has operator<.

    Alternatively, you should consider writing your own hash function and most likely your own comparator in order to fit your usecase, I see that you tried to use the output of to_string() of the address in your comparator. Maybe you can hash the output of to_string() to implement the hash function and use string comparison(on the output of to_string()) for the comparison function.