pushE
pushE

Reputation: 414

How can i compare two properties of struct in a single SET?

My code is as below. I have as struct ABC and i have set g_ABCSet to compare the 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];
    }
}

I try to search in set as below comparing the 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
}

My query here is can i use the same set to compare the "Cstring name" in the ABC struct.

If YES HOW ??

IF NO , DO i need to make same new set ,overlaod operator to comparing Cstring and insert all same pointers to new set also ??

Upvotes: 0

Views: 255

Answers (1)

Andreas H.
Andreas H.

Reputation: 1811

No you cannot use a single std::set.

Why: Because the set requires the keys to be in 'strict ordering'. Most likely the set uses a tree structure to store it's items and the tree is sorted by the given comparator.

This means also that if you insert multiple items with different names and identical ids, only one items is stored at all (because the Comparator says they are all identical)

You can use std::find_if to search for Cstring name:

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

If you have a large set of items in g_ABCSet you should do as you wrote: create a second set with a Comparator for 'name'.

Tip: If you use std::array<byte, 2> id instead of byte id[2] your Comparator could be as simple as

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

Maybe you better use a std::map<std::array<byte, 2>, ABC_PTR> and another std::map<CString, ABC_PTR> for this job. This needs more memory (mostly because of the CString being copied from the g_ABCSet into the map) but get completly rid of the custom Comparators and you cannot accidentally use the wrong set (with the wrong Comparator)

Upvotes: 1

Related Questions