0

I have a wrapper class around uint32_t:

class IPv4 
{ 
  uint32_t octets_;
public:
  operator uint32_t() {return octets;} 
};

Also I have a structure inherited from IPv4 class:

struct routerID : public IPv4 
{};

I want to create an unordered_map:

std::unordered_map<RouterID, std::string> routers;

But I’ve got an error: attempting to reference a deleted function.

Is there a way to make it working without explicitly defining hash_function and == for my IPv4 class?

7
  • Then, since C++20 you can default your comparison operator Commented May 8, 2024 at 9:08
  • @pptaszni My RouterID class, is, in fact, uint32_t (it can be implicitly casted to uint32_t). So, I don’t want to define hash function and comparison operator just for uint32_t. Or is it necessary for unordered map? Commented May 8, 2024 at 9:14
  • 3
    A hash<IPv4>, delegating to existing hash, would be a one-liner. Commented May 8, 2024 at 9:16
  • If you would do using RouterID = std::uint32_t; , then yes, you could say it is in fact uint32_t. Otherwise, it's a distinct type, no matter how simple. Commented May 8, 2024 at 9:18
  • 2
    Having an implicit conversion to uint32_t removes some of the advantages you gain by having a custom type in the first place, IMO. Commented May 8, 2024 at 9:24

1 Answer 1

1

Just add the stupid hash. There is no benefit in trying to minimize lines of code.

#include <unordered_map>
#include <cstdint>
#include <string>

class IPv4
{
  uint32_t octets_;
public:
  operator uint32_t() const {return octets_;}
};

struct RouterID : public IPv4
{};

template <> struct std::hash<RouterID>
{
    std::size_t operator()(const RouterID& routerId) const noexcept
    {
        return std::hash<uint32_t>{}(routerId);
    }
};

std::unordered_map<RouterID, std::string> routers;

You could, also, just do a

std::unordered_map<RouterID, std::string, std::hash<uint32_t>> routers;

Myself, I'm not the biggest fan of this -- having an actual std::hash for the RouterID does tell the reader that a hash is used somewhere, and makes it explicit how that hash is calculated.

Sign up to request clarification or add additional context in comments.

5 Comments

Ok, thank you, I thought defining operator uint32_t() would be enough
You could, conceivably, also do something like this: std::unordered_map<RouterID, std::string, std::hash<uint32_t>> routers;
No, I checked and that does not compile
@razenkovv works here
@Caleth Thank you, forget to add const to operator uint32_t()

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.