在C++20中,在std::unordered_set<std::unique_ptr>中查找指向T类型的指针。

6
使用std::unique_ptr的std::unordered_set中所指出的,要在std::unordered_set<std::unique_ptr<T>>中找到指针T*并不容易。在C++20之前,我们被迫构造一个std::unique_ptr<T>实例。

由于“无序容器的异质查找”提案(http://wg21.link/P0919r3http://wg21.link/p1690r1),这个问题在C++20中得到解决。但可用的解决方案对我来说看起来相当笨拙(即使按照C++标准)。似乎我需要从头开始实现两个函数对象(用于透明哈希和透明比较):
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>>;

演示:https://gcc.godbolt.org/z/bqx714(该提议目前仅在MSVC中实现)。
这个方法可行,但是似乎有很多样板代码。我错过了什么吗?是否有一种方法可以使用IDK(不知道)也许一些标准的透明哈希或相等比较器?我看到std :: equal_to<void>是透明的,但我无法直接使用它。也许有一种狡猾的方式来定义unique_ptr<T> -> T*隐式转换,“只为此UnorderedSetOfUniquePtrs类”?欢迎您的想法。
1个回答

4
您可以将冗长的输出转移到std::to_address(感谢@Caleth指出这一点)和现有的std::hash中,后者被专门用于std::unique_ptr,以便基于原始地址返回哈希值(感谢@Mikhail的提示)。 然后使用成员函数模板实现哈希和相等类型(请注意,您不再需要自己是模板类型):
struct Equal {
    using is_transparent = void;
    template<class U, class S>
    bool operator()(const U& lhs, const S& rhs) const { 
        return std::to_address(lhs) == std::to_address(rhs); 
    }
};

struct Hash {
    using is_transparent = void;
    template<class U>
    size_t operator()(const U& ptr) const {
        return std::hash<U>{}();
    }
}

1
缺少对hash调用的参数ptr - Roman Orekhov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接