【问题标题】:Find by equivalent key in unordered_set of shared_ptr’s通过 shared_ptr 的 unordered_set 中的等效键查找
【发布时间】:2021-09-02 13:27:36
【问题描述】:

在 C++20 中,关联散列容器接收新的 find 方法,这些方法可以在输入时接受等效的键类型。例如,在std::unordered_set

template< class K > iterator find( const K& x ); //(3)  (since C++20)

https://en.cppreference.com/w/cpp/container/unordered_set/find

在这个例子中,我尝试使用 rawpainter 在 shared_ptrs 的容器中搜索:

#include <unordered_set>
#include <memory>

using sptr = std::shared_ptr<int>;

struct ptr_equal
{
    using is_transparent = void;
    bool operator()(const sptr& l, const sptr& r) const { return l == r; }
    bool operator()(const sptr& l, const int* r) const { return l.get() == r; }
    bool operator()(const int* l, const sptr& r) const { return l == r.get(); }
};

struct ptr_hash : public std::hash<const int*>
{
    using is_transparent = void;
    std::size_t operator()(const sptr& s) const
       { return std::hash<const int*>::operator()(s.get()); }
    std::size_t operator()(const int* s) const
       { return std::hash<const int*>::operator()(s); }
};

int main()
{
    auto v = std::make_shared<int>(0);
    std::unordered_set<sptr, ptr_hash, ptr_equal> set{v};
    set.find( v.get() ); //still clang error here
}

它适用于 gcc 11,但不适用于 clang 12:https://gcc.godbolt.org/z/P9E5TTba4

source>:27:9: error: no matching member function for call to 'find'

是程序有问题还是clang还不支持新的find方法?

【问题讨论】:

  • 可能只是它还没有在clang中实现。我不相信任何编译器都完全兼容 C++20。 en.cppreference.com/w/cpp/compiler_support
  • 将您的 Compiler Explorer 示例更改为“clang (trunk)”编译成功,所以这似乎是您的答案。
  • 如果你使用clang的trunk版本,它实际上会编译。
  • 注意:我会怀疑struct ptr_hash : public std::hash&lt;const int*&gt;。如果你想为这个private 使用继承,继承应该可以完成这项工作。公共继承使您面临对象切片等风险。 std::hash 不是多态的,也不是为了继承而设计的,所以在公开继承它时必须非常小心,而私有继承没有风险。

标签: c++ c++20 unordered-set


【解决方案1】:

上述程序在 C++20 中是正确的。编译失败是clang 12的一个限制。

但有人建议我使用一种更简单的技术来解决原始问题(通过原始指针在具有std::shared_ptr 键的容器中搜索,没有任何堆分配/释放),该技术从 C++11 开始工作:

#include <unordered_set>
#include <memory>

using sptr = std::shared_ptr<int>;

int main()
{
    auto v = std::make_shared<int>(0);
    std::unordered_set<sptr> set{v};
    set.find( sptr{ std::shared_ptr<void>(), v.get() } );
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-19
    • 2011-01-30
    • 1970-01-01
    相关资源
    最近更新 更多