Reputation:
I am trying to use the std::set
to contain a struct of three member variables.
struct blah{
int a,b,c;
bool operator < ( const blah& blo ) const{
return ( a < blo.a || (a == blo.a && (b != blo.b || c != blo.c ) ) );
}
};
But I keep getting an error that my operator < is invalid. What is wrong with my approach?
struct blah {
int a,b,c;
blah(int aa,int bb,int cc){ a=aa; b=bb; c=cc; }
bool operator < ( const blah& blo ) const{
return ( a < blo.a
|| (a == blo.a && b < blo.b )
|| (a == blo.a && b == blo.b && c < blo.c )
);
}
};
int main() {
std::set<blah> st;
st.insert(blah(1,2,3));
st.insert(blah(1,1,1));
st.insert(blah(1,3,2));
return 0;
}
After altering the code following @paxdiablo code, this worked well. Thanks y'all!
Upvotes: 0
Views: 264
Reputation: 881313
That code compiles fine for me in the following complete program:
#include <iostream>
struct blah {
int a,b,c;
bool operator < ( const blah& blo ) const{
return ( a < blo.a || (a == blo.a && (b != blo.b || c != blo.c ) ) );
}
};
int main (void) {
blah x, y;
x.a=2; x.b=2; x.c=2;
y.a=2; y.b=2; y.c=2;
if (x < y) std::cout << "x<y\n";
if (y < x) std::cout << "x>y\n";
if (!(y < x) && !(x < y)) std::cout << "x=y\n";
return 0;
}
Changing the fields of x
and y
outputs different messages.
But I see one major problem with the function. It can tell you that both x < y
and y < x
, in the situation where the two a
fields are identical but the b
fields differ between the two. If you set both a
fields to 1 and set the b
fields to 2
and 1
, you see:
x<y
y<x
That's not going to end well :-)
The fact that what you're getting is a debug assertion (something specifically built to catch runtime errors in mostly debug code) leads me to believe that the runtime libraries may explicitly be checking for incorrect operator<
overloads by detecting that latter case (ie, both x < y
and y < x
are true).
You should really fix that because it will cause all sorts of problems with collections where (for example) you need to keep things sorted.
By way of example, let's say you wanted to use a
, b
and c
as keys in that priority. A function to do that would contain something like:
// Check primary key.
if (a < blo.a) return true;
if (a > blo.a) return false;
// Primary key equal here, use secondary key.
if (b < blo.b) return true;
if (b > blo.b) return false;
// Primary and secondary keys equal here, use tertiary key.
return (c < blo.c);
Upvotes: 4