Using std::unordered_set with Smart Pointers

How can I store smart pointers like std::unique_ptr in a std::unordered_set?

To store smart pointers like std::unique_ptr in a std::unordered_set, you need to provide a custom hash function and a custom equality comparator that operate on the underlying raw pointers.

Here's an example of using std::unique_ptr with std::unordered_set:

#include <iostream>
#include <memory>
#include <unordered_set>

struct Player {
  std::string Name;
  int Score;

  Player(const std::string& Name, int Score)
    : Name{Name}, Score{Score} {}
};

struct PlayerHash {
  size_t operator()(
    const std::unique_ptr<Player>& P) const {
    return std::hash<Player*>{}(P.get());  
  }
};

struct PlayerEqual {
  bool operator()(
    const std::unique_ptr<Player>& A,
    const std::unique_ptr<Player>& B
  ) const {
    return A.get() == B.get();  
  }
};

int main() {
  std::unordered_set<std::unique_ptr<Player>,
    PlayerHash, PlayerEqual> Players;  

  Players.emplace(
    std::make_unique<Player>("Alice", 100));
  Players.emplace(
    std::make_unique<Player>("Bob", 200));

  for (const auto& Player : Players) {
    std::cout << Player->Name << ": "
      << Player->Score << "\n";
  }
}
Alice: 100
Bob: 200

In this example:

  • We define a Player struct with Name and Score members
  • We create a PlayerHash struct that overloads operator() to hash the raw pointer stored inside the std::unique_ptr
  • We create a PlayerEqual struct that overloads operator() to compare the raw pointers stored inside the std::unique_ptrs for equality
  • We specify std::unique_ptr<Player> as the key type and provide PlayerHash and PlayerEqual as the hash function and equality comparator when creating the std::unordered_set
  • We use std::make_unique to create std::unique_ptr<Player> objects and insert them into the set using emplace()

By providing custom hash and equality functions that operate on the raw pointers, we enable std::unordered_set to store and compare std::unique_ptr<Player> objects correctly.

Note that using smart pointers in an unordered set compares the pointers themselves, not the objects they point to. If you want to compare the pointed-to objects, you'll need to dereference the smart pointers in your custom comparator and hash function.

Hash Sets using std::unordered_set

This lesson provides a thorough understanding of std::unordered_set, from basic initialization to handling custom types and collisions

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Implementing a Custom Hash Function
How can I implement a custom hash function for my user-defined type to use with std::unordered_set?
Erasing Elements while Iterating
Is it safe to erase elements from a std::unordered_set while iterating over it?
Using a Custom Allocator with std::unordered_set
How can I use a custom allocator with std::unordered_set?
Difference between rehash() and reserve()
What is the difference between rehash() and reserve() in std::unordered_set?
Checking if a Key Exists without Inserting
How can I check if a key exists in a std::unordered_set without inserting it if it doesn't?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant