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

pir*_*iri 7 c++ stl set

考虑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;
}
Run Code Online (Sandbox Code Playgroud)

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

我想找一个A具有给定值的A::ain sa,而不构造一个类型的临时对象A,即我正在寻找类似的东西

sa.find(4)
Run Code Online (Sandbox Code Playgroud)

使用自定义比较器,允许直接比较整数与类型的对象A.那可能吗?

use*_*670 13

使用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;
}
Run Code Online (Sandbox Code Playgroud)

在线编译器

在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;
}
Run Code Online (Sandbox Code Playgroud)

在线编译器

  • @piripiri 这允许根据成员的使用和关系对成员进行分组,提高可读性(无需向上滚动以检查特定成员的可见性),简化重构(无需移动代码)。大多数较新的语言(java、c#、D)*需要*每个成员的访问说明符,因为事实证明这种方法更好。 (2认同)