Reputation: 493
I have a self-made struct
and I want to compare two instance of it. In order to do that I obviously overload the operator==
so I will be able to do so. Now, this operator may be called with 0 to 2 const
instances and 0 to 2 non-const
instances.
As I want my operator ==
to compare 2 const as it compare any possible combination of const
and non-const
, the best for me should be to write only one overload which can deal with all possible combination. But as far as I know, I didn't find any way to do so.
Does that mean that if I need to consider all possible combination, I have to write all 4 possible overloads ? Is there anyway I can avoid to write 4 times the same function only with const
keywords changing ?
So here is the struct
. It represents an object on a plan, and consists of its position and a value associated to it:
struct Foo
{
int x;
int y;
double value;
};
Now let's say 2 Foo
are equal if they have the same value and the same position. I have the following operator:
inline bool operator==(Foo object) // Compare two non-const Foo
{
return (x == object.x) && (y == object.y) && (value == object.value);
}
But, eww, unlucky some Foo
can be constants, meaning that my objects can't move on the plan and can't change their value. And now I need to check if two const Foo
can be equals and if a non-const Foo
can be equal to a const Foo
.
Is there anyway I can do that but still avoid to write those following functions which are almost the same as the first one ?
inline bool operator==(const Foo &object) // Compare a non-const Foo with a const Foo
{
return (x == object.x) && (y == object.y) && (value == object.value);
}
inline bool operator==(const Foo &object) const // Compare two const Foo
{
return (x == object.x) && (y == object.y) && (value == object.value);
}
inline bool operator==(Foo object) const // Compare a const Foo with a non-const Foo
{
return (x == object.x) && (y == object.y) && (value == object.value);
}
I don't have any requirements on c++ version. It can ever be c++17 or c++20.
Upvotes: 1
Views: 217
Reputation: 37616
If you have a non-const
Foo
object, you can use it where const Foo&
object are expected, and you can call const
-method on it, so you should only have one overload:
bool operator==(Foo const& object) const {
return (x == object.x) && (y == object.y) && (value == object.value);
}
You only needs to differentiate const
and non-const
overloads for specific cases where the behavior is different depending if the object is const
or non-const
, e.g., for operator[]
:
// You want to return a reference on non-const object and a const-reference
// on const object, so you need both overloads.
X& operator[](std::size_t);
const X& operator[](std::size) const;
You usually want to have non-member functions for binary operators, with friend
if necessary. In your case, since all members are public, you can simply create a free function (outside the struct
):
bool operator==(Foo const& lhs, Foo const& rhs) const {
return lhs.x == rhs.x && lhs.y == rhs.y && lhs.value == rhs.vallue;
}
You can also drop that inline
modifier which is kind of irrelevant nowadays, see, e.g., When should I write the keyword 'inline' for a function/method?.
You can also check What are the basic rules and idioms for operator overloading? for some idioms regarding operator overloading.
Upvotes: 1
Reputation:
Operator==, like most binary operators, should normally be implemented as a single, non-member, free function:
inline bool operator==(const Foo & a, const Foo & b ) {
return a.x == b.x && a.y == b.y && a.value == b.value;
}
Upvotes: 2
Reputation: 2552
There is no reason to do so!
As long as it is just comparison then it is preferred always to use const references
:
inline bool operator==(const Foo &object)const{
return (x == object.x) && (y == object.y) && (value == object.value);
}
The reason is you can pass the address or reference of const
and non-const
to a const
member function but not the contrary.
There are some cases when overloading depending on constness
matters.
Upvotes: 1