C++ equal(==) overload, Shortcut or best way comparing all attributes
Starting in C++11 with the introduction of tuples we also got std::tie()
. This will let use make a tuple out of a bunch of variables and call a comparison function against all of them. You can use it like
struct Foo
{
int a,b,c,d,e,f;
bool operator==(const Foo& rhs) { return std::tie(a,b,c,d,e,f) == std::tie(rhs.a,rhs.b,rhs.c,rhs.d,rhs.e,rhs.f); }
};
You still have to list all the members you want to check but it makes it easier. You can also use this to make less than and greater than comparisons much easier.
It should also be noted that the variables are checked in the order you provide them to tie
. This is important for less than and greater than comparisons.
std::tie(a,b) < std::tie(rhs.a, rhs.b);
Does not have to be the same as
std::tie(b,a) < std::tie(rhs.b, rhs.a);
At the moment, there is no shortcut but there are plans to add support for it (P0221R0).
Bjarne Stroustrup recently wrote a blog post about it: A bit of background for the default comparison proposal
In C++14, there is nothing better than listing all members and comparing them, which is error prone. To quote Bjarne:
The killer argument for default comparisons is not actually convenience, but the fact that people get their equality operators wrong.
There is no shortcut. You will have to list everything.
Some sources of error can be reduced by introducing a member function named tied()
like:
struct Foo {
A a;
B b;
C c;
...
private:
auto tied() const { return std::tie(a, b, c, ...); }
};
So that your operator==
can just use that:
bool operator==(Foo const& rhs) const { return tied() == rhs.tied(); }
This lets you only list all your members once. But that's about it. You still have to actually list them (so you can still forget one).
There is a proposal (P0221R0) to create a default operator==
, but I don't know if it will get accepted.
The above proposal was rejected in favor of a different direction regarding comparisons. C++20 will allow you to write:
struct Foo {
A a;
B b;
C c;
// this just does memberwise == on each of the members
// in declaration order (including base classes)
bool operator==(Foo const&) const = default;
};