I am trying to assign a custom type as a key for std::map. Here is the type which I am using as key.
struct Foo
{
Foo(std::string s) : foo_value(s){}
bool operator<(const Foo& foo1) { return foo_value < foo1.foo_value; }
bool operator>(const Foo& foo1) { return foo_value > foo1.foo_value; }
std::string foo_value;
};
When used with std::map, I am getting the following error.
error C2678: binary '<' : no operator found which takes a left-hand operand of type 'const Foo' (or there is no acceptable conversion) c:\program files\microsoft visual studio 8\vc\include\functional 143
If I change the struct like the below, everything worked.
struct Foo
{
Foo(std::string s) : foo_value(s) {}
friend bool operator<(const Foo& foo,const Foo& foo1) { return foo.foo_value < foo1.foo_value; }
friend bool operator>(const Foo& foo,const Foo& foo1) { return foo.foo_value > foo1.foo_value; }
std::string foo_value;
};
Nothing changed except making the operator overloads as friend. I am wondering why my first code is not working?
Any thoughts?
I suspect you need
Note the
const
after the arguments, this is to make "your" (the left-hand side in the comparison) object constant.The reason only a single operator is needed is that it is enough to implement the required ordering. To answer the abstract question "does a have to come before b?" it is enough to know whether a is less than b.
It's probably looking for const member operators (whatever the correct name is). This works (note const):
EDIT: deleted
operator>
from my answer as it was not needed (copy/paste from question) but it was attracting comments :)Note: I'm 100% sure that you need that const because I compiled the example.
Note the const after the arguments, this is to make "your" (the left-hand side in the comparison) object constant.
Could you please elaborate on this? Why if you make the member const (which as far as I know means that it can't change object's state - e.g. modify private variables) guarantees that "your" will be the left-hand side?
I don't yet have the rep to comment on this.
const does not magically ensure that "your" will be the left hand side. The poster was saying that the left hand side (i.e. x in x < y) is the object on which the comparison is being called. Just as you protect y's members from change with the const on the argument to operator<, you also want to protect x's members from change with the const at the end of the method signature.