• Status: Solved
• Priority: Medium
• Security: Public
• Views: 565

# std::map comparator

``````struct type {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
};

std::map<type, uint32_t>my_map;

operator<(const type& n1, const type& n2) {
if (n1.a < n2.a)
return true;
if (n1.a > n2.a)
return false;
if (n1.b < n2.b)
return true;
if (n1.b > n2.b)
return false;
if (n1.c < n2.c)
return true;
if (n1.c > n2.c)
return false;
if (n1.d < n2.d)
return true;
if (n1.d > n2.d)
return false;

return false;
}
``````

Is there a better way of writing < comparator then the one I wrote. The above looks ugly and lengthy. I mean is there a shorter way of writing this by Boost or something else?
0
perlperl
• 4
• 4
• 2
• +1
1 Solution

Commented:

``````operator<(const type& n1, const type& n2) {
return !(n1.a < n2.a || n1.b < n2.b || n1.c < n2.c || n1.d < n2.d);
}
``````

Will it be more readable than yours? I don't think so.
0

Commented:
you can/should add the operator< as member to the struct:

``````struct type {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;

bool operator<(const type& t)
{
return (a < t.a) ||
(a == t.a && b < t.b) ||
(a == t.a && b == t.b && c < t.c) ||
(a == t.a && b == t.b && c == t.c && d <= t.d);

}
};
``````

Sara
0

Author Commented:
chaau, I don't think so your one liner handles all the case, it ignores the case of "=="
I am sure there might be a fancy way to do this using boost, just couldn't find it :)
0

Author Commented:
1) Also why do I have to include all the members of structure in < comparator.
Why can't I just write
return (a < t.a) ;

2) Also do we always have to overload < operator for struct or class as Key of std::map.

3) When do we overload () operator or == or !=
0

Commented:
Why can't I just write
return (a < t.a) ;

of course you can do. but than two entries t1 and t2 where t1.a == t2.a are equal. if you don't have such entries (what means that member a is key), i wonder why your map has struct type as key and not only uint32_t for the a member of the type.

note, a map needs to have a unique key.

Sara
0

Author Commented:
the members of my type are not unique. Two entries can have same few members, when I combine all members, they are considered unique.

now I got it, just to make sure the key is unique, I need to include all my members.
0

Commented:
to make the comparision easier you could convert the a, b, c, d to a hex string and then compare the strings:

``````struct type {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;

std::string uToHex(uint32_t u)
{
std::ostringstream os;
os << std::hex << std::right << std::setfill('0') << std::setw(8) << (unsigned int)u;
return os.str();
}
bool operator<(const type& t)
{
std::ostringstream os1, os2;
os1 << uToHex(a) << uToHex(b)<< uToHex(c)<< uToHex(d);
os2 << uToHex(t.a) << uToHex(t.b)<< uToHex(t.c)<< uToHex(t.d);
return os1.str() < os2.str();
}
...
``````

2) Also do we always have to overload < operator for struct or class as Key of std::map.

you can pass a compare function or a functor as 3rd template argument to your map. but actually it doesn't make it easier. a key for a map always needs to have the same compare function. so if the key is a class or struct type you always should provide an operator<. in case of pointers, it is different.

3) When do we overload () operator or == or !=
operator() for example was overloaded for a functor. a functor was a helper class which - shortly said - provides a function pointer by means of operator() overload.
another usage for operator() is for example a string class where you do

``````MyString str = another_string(1, 2);
``````

and where operator() would provide substring functionality.

operator!= should be overloaded if you have operator== overloaded. note, std::map doesn't need operator== cause it could find out equality by use of less function: !((a < b) || (b < a)).

you would provide operator== for your class or struct when you need the operation for your own purposes.

Sara
0

Author Commented:

so basically for map, we don't have to overload () or != or ==

just overloading '<' would be suffice for insert() and find() method on map ??
0

Commented:
>> os << std::hex << std::right << std::setfill('0') << std::setw(8) << (unsigned int)u;
If performance is any concern, then this will cause multiple time-consuming allocations.
0

Commented:
yes. the operator< is sufficient.

Sara
0

Commented:
@perlperl: my one liner handles == just well. It returns false like an original operator. Just FYI. As I mentioned it is less readable, but it does the job
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.