如何在单个SET中比较struct的两个属性?

时间:2018-04-18 01:54:56

标签: c++ set compare operator-overloading st

我的代码如下。 我有结构ABC,我已经设置了g_ABCSet来比较id。

struct ABC
{
CString name;
byte id[2];
}

typedef shared_ptr<ABC> ABC_PTR;

std::set<ABC_PTR, CompareABC> g_ABCSet;

class ComparePager{
public:
    bool operator()(const ABC_PTR& m1, const ABC_PTR& m2) const {
        if (m1->id[0] == m2->id[0]){
            return m1->id[1] < m2->id[1];
        }
        return m1->id[0] < m2->id[0];
    }
}

我尝试在下面搜索比较id

static ABC_PTR ABCptr(new ABC);
//Assume ABCptr have some valid ID 
auto it = g_ABCSet.find(ABCptr);
if (it == g_ABCSet.end())
 {
//not found
}
else
{
 //found one
}

我在这里的查询是否可以使用相同的集来比较&#34; Cstring名称&#34;在ABC结构中。

如果是,如何?

如果不是,我需要制作相同的新集合,重叠运算符来比较Cstring并将所有相同的指针插入到新集合中吗?

1 个答案:

答案 0 :(得分:1)

不,你不能使用单个std :: set。

原因:因为该套装要求按键处于严格的排序状态&#39;。很可能该集合使用树结构来存储它的项目,并且树由给定的比较器排序。

这也意味着如果您插入具有不同名称和相同ID的多个项目,则根本只存储一个项目(因为比较器说它们都是相同的)

您可以使用std :: find_if搜索Cstring name

CString searchName = "...";
auto it = std::find_if(
  g_ABCSet.begin(), 
  g_ABCSet.end(), 
  [&](const ABC_PTR& ptr) {
     return ptr->name == searchName;
  });

如果您在g_ABCSet中有大量项目,则应该按照自己的意愿进行操作:使用比较器创建第二个名称&#39;。

提示:如果您使用std::array<byte, 2> id代替byte id[2],则您的比较器可能就像

一样简单
class ComparePager{
public:
    bool operator()(const ABC_PTR& m1, const ABC_PTR& m2) const {
        return m1->id < m2->id;
    }
}

也许您最好使用std::map<std::array<byte, 2>, ABC_PTR>和另一个std::map<CString, ABC_PTR>来完成这项工作。这需要更多的内存(主要是因为CString被从g_ABCSet复制到地图中)但是完全摆脱了自定义比较器,你不会意外地使用错误的设置(使用错误的比较器)