通过与不同类型的值进行自定义比较来查找 std::set 的元素

Find elements of std::set by custom comparison with value of different type

本文关键字:查找 比较 std 元素 set 自定义 同类型      更新时间:2023-10-16

考虑以下带有自定义比较器的std::set玩具示例:

#include <set>
struct A {
  A() : a(cnt++) {}
  const int a;
  static int cnt;
};
int A::cnt = 0;
struct comp {
  bool operator()(const A& left, const A& right)
  {
    return left.a < right.a;
  }
};
int main()
{
  std::set<A, comp> sa;
  for (int i = 0; i < 10; ++i) sa.insert(A());
  return 0;
}

请注意,不能简单地从整数创建A

我想在 sa 中寻找给定值为 A::aA而不构造类型 A 的临时对象,即我正在寻找类似

sa.find(4)

使用自定义比较器,允许将整数与类型A的对象直接进行比较。这可能吗?

使用 C++14,您可以使用"透明"比较器:

#include <iostream>
#include <set>
#include <type_traits>
class A
{
    public: explicit A() : a{cnt++} {}
    private: explicit A(int) = delete;
    public: const int a;
    private: static int cnt;
};
int A::cnt{};
class Comparator
{
    // this member is required to let container be aware that 
    // comparator is capable of dealing with types other than key
    public: using is_transparent = std::true_type;
    public: bool operator()(const int & left, const A& right) const
    {
        return left < right.a;
    }
    public: bool operator()(const A & left, const int& right) const
    {
        return left.a < right;
    }
    public: bool operator()(const A& left, const A& right) const
    {
        return left.a < right.a;
    }
};
int main()
{
    std::set<A, Comparator> sa{};
    for (int i{}; i < 10; ++i)
    {
        sa.emplace();
    }
    std::cout << sa.find(3)->a << std::endl;
    return 0;
}

在线编译器

在 C++14 之前,异构查找在::boost::intrusive::set中可用:

#include <boost/intrusive/set.hpp>
#include <iostream>
namespace bi = ::boost::intrusive;
// hook contains set node data, supports various options, can be a member
class A: public bi::set_base_hook
<
    bi::link_mode<bi::link_mode_type::safe_link>
>
{
    public: explicit A() : a{cnt++} {}
    private: explicit A(int) = delete;
    public: const int a;
    private: static int cnt;
};
int A::cnt{};
class Comparator
{
    public: bool operator()(const int & left, const A& right) const
    {
        return left < right.a;
    }
    public: bool operator()(const A & left, const int& right) const
    {
        return left.a < right;
    }
    public: bool operator()(const A& left, const A& right) const
    {
        return left.a < right.a;
    }
};
int main()
{
    bi::set<A, bi::compare<Comparator>> sa{Comparator{}};
    for (int i{0}; i < 10; ++i)
    {
        sa.insert(*new A{}); // typically user manages object creation
    }
    // comparators may vary
    std::cout << sa.find(3, Comparator{})->a << std::endl;
    return 0;
}

在线编译器

相关文章: