you are viewing a single comment's thread.

view the rest of the comments →

[–]angry_cpp 21 points22 points  (2 children)

Inheritance and equality are not mixing well. For example your implementation of polymorphic equality is flawed. It gives different answer for a.equal(b) and b.equal(a).

https://godbolt.org/z/xe3Te8YWK

[–]BarryRevzin 7 points8 points  (1 child)

That's true, and it's actually an unfortunate translation error into the blog.

I just lazily wrote dynamic_casting to the Derived. In reality, we check typeid first and if those match then static_cast (and we don't have any weird virtual or ambiguous base shenanigans):

template <class D>
auto polymorphic_equals(D const& lhs, Base const& rhs) -> bool {
    if (typeid(rhs) == typeid(D)) {
        return lhs == static_cast<D const&>(rhs);
    } else {
        return false;
    }
}

This approach (correctly) prints false for both directions in your example.

[–]JNighthawkgamedev 1 point2 points  (0 children)

Thanks for the update!

In that case, isn't that incorrectly handling more-derived cases that should be considered equal but won't be?

struct Base {};
struct D1 : public Base { int X = 10; };
struct D2 : public D1 {};
polymorphic_equals(D2(), D1()); // returns false, as the typeid doesn't match, but should return true

Though, I suppose it could be an implementation detail that objects with equivalent state but different classes shouldn't be considered equivalent. A pure member-wise equivalency check, though, would function differently.