As pointed out in Using a std::unordered_set of std::unique_ptr, it is not easy to find a pointer T* in std::unordered_set<std::unique_ptr<T>>. Prior to C++20 we were forced to construct an instance of std::unique_ptr<T>.
Thanks to the Heterogeneous lookup for unordered containers proposals (http://wg21.link/P0919r3 and http://wg21.link/p1690r1), this problem is solved in C++20. But the available solution looks quite clumsy to me (even by C++ standards). It seems like I need to implement from scratch not one, but two functors (for transparent hashing and for transparent comparison):
template<class T>
struct Equal {
    using is_transparent = void;
    bool operator()(const std::unique_ptr<T>& lhs, const std::unique_ptr<T>& rhs) const {
        return lhs == rhs;
    }
    bool operator()(const std::unique_ptr<T>& lhs, const T* rhs) const {
        return lhs.get() == rhs;
    }
    bool operator()(const T* lhs, const std::unique_ptr<T>& rhs) const {
        return lhs == rhs.get();
    }
};
template<class T>
struct Hash {
    using is_transparent = void;
    size_t operator()(const std::unique_ptr<T>& ptr) const {
        return std::hash<const T*>()(ptr.get());
    }
    size_t operator()(const T* ptr) const {
        return std::hash<const T*>()(ptr);
    }
};
template<class T>
using UnorderedSetOfUniquePtrs = std::unordered_set<std::unique_ptr<T>, Hash<T>, Equal<T>>;
Demo: https://gcc.godbolt.org/z/bqx714 (the proposal is currently implemented only in MSVC).
This works but looks like A LOT of boilerplate. Am I missing something? Is there a way to use IDK maybe some standard transparent hasher or equality comparator? I see that std::equal_to<void> is transparent, but I cannot use it directly. Maybe there is a sneaky way to define unique_ptr<T> -> T* implicit conversion "just for this UnorderedSetOfUniquePtrs class"? Your ideas are welcomed.