How to use a struct in std::map?
I have a complex struct i want to put as a key of the std::map to make a list of all unique objects fast:
union somecomplexstruct {
struct {
more_structs val1, val2;
even_more_structs val3, val4;
lots_of_more_structs val5;
};
unsigned int DATA[3];
};
typedef map<somecomplexstruct, int, greater<somecomplexstruct> > somecomplexstructMap;
But it says error: error C2784: 'bool std::operator >(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::vector<_Ty,_Alloc> &' from 'const somecomplexstruct'
How do i make my struct work there?
Edit: Got it working, thanks to everyone! Heres the code:
inline bool operator>(const somecomplexstruct &v1, const somecomplexstruct &v2){
if(v1.DATA[0] > v2.DATA[0]) return 1;
if(v1.DATA[0] < v2.DATA[0]) return 0;
if(v1.DATA[1] > v2.DATA[1]) return 1;
if(v1.DATA[1] < v2.DATA[1]) return 0;
ret开发者_运维问答urn v1.DATA[2] > v2.DATA[2];
}
std::greater<>
invokes operator>()
to do its work, so you need to overload that if you want to use std::greater<>
.
It should look like this:
inline bool operator>(const somecomplexstruct& lhs, const somecomplexstruct& rhs)
{
// implement your ordering here.
}
With your operator>
function, consider what happens if you compare {1, 0, 0}
and {0, 1, 0}
. If you compare a > b
, it returns true from the first comparison. If you compare b > a
it returns true from the second comparison. So its fails the reflexive property for comparisons, scrambling the map. In order for map to work properly, you must define your operator> such that a > b
== !(b > a)
for all possible non-equal pairs of values that might be compared.
edit
The easiest/best way to ensure that your operator is properly reflexive is to ensure the for every test that might return true, you also have a test with the same condition and the operands swapped that returns false. So if you have
if(v1.DATA[1] > v2.DATA[1]) return 1;
in your function, you need
if(v2.DATA[1] > v1.DATA[1]) return 0;
or the equivalent somewhere.
Here is lexicographical comparator for a complex structure
struct D {
struct A {
bool operator <(const A &) const;
} a;
struct B {
bool operator <(const B &) const;
} b;
struct C {
bool operator <(const C &) const;
} c;
template <class T> ne(const T & a, const T & b) {
if (a < b) return true;
if (b < a) return true;
return false;
}
bool operator < (const D & that) const {
if (ne(a, that.a)) return a < that.a;
if (ne(b, that.b)) return b < that.b;
return c < that.c;
}
};
If your map contains only pointers to your struct, you don't have to do all that complicated operator overloading.
Therefore your typedef looks like this:
typedef map<somecomplexstruct*, int, greater<somecomplexstruct*> > somecomplexstructMap;
Structs typically have only public data members and no need for operator overloading.
This means though that you have to be careful about when and how you release the memory for the pointers. There's pros and cons to each approach, as with everything.
精彩评论