How to avoid forgetting to define operator == in subclasses?

I have a base class and set the == operator on it. And B is a subclass of A , and I forgot to define operator== on B Then A::operator== used when comparing B , and usually it gives unexpected results. Any good way to avoid such a β€œforget”? I am adding an example to clarify my question.

 class A { public: bool operator==(const A& rhs) const { return i == rhs.i; } int i }; class B : public A { public: int j; } B b1, b2; b1.i = 1; b1.j = 2; b2.i = 1; b1.j = 3; bool b = (b1 == b2); // will be true 
+4
source share
3 answers

Enabling implicit conversions for greatwolf's great approach is a bit trickier:

 #include <type_traits> namespace stuff { template<class T, class U> bool operator== (const T &lhs, const U &rhs) { using namespace std; static_assert(is_convertible<T, U>{} || is_convertible<U, T>{}, "invalid argument type"); static_assert ( is_same<T, U>{} || ( not is_base_of<T, U>{} && not is_base_of<U, T>{}) , "use explicit casts to compare derived to base class types" ); return is_equal(lhs, rhs); } template<class T> bool is_equal(T const&, T const&) { // force compile-time failure when instantiating static_assert(std::is_same<T, void>{}, "no free is_equal function for these argument types available"); return false; } class A { private: int i; friend bool is_equal(A const& lhs, A const& rhs) { return lhs.i == rhs.i; } public: A(int p_i) : i(p_i) {} }; class B : public A { int j; public: B(int p_i, int p_j) : A(p_i), j(p_j) {} }; class C : public A { private: int j; friend bool is_equal(C const& lhs, C const& rhs) { return is_equal(static_cast<A const&>(rhs), static_cast<A const&>(lhs)) && lhs.j == rhs.j; } public: C(int p_i, int p_j) : A(p_i), j(p_j) {} }; } struct D { operator stuff::C() const { return stuff::C(1, 42); } }; #include <iostream> int main() { stuff::A a(1), aa(1); stuff::B b(1, 42), bb(1, 42); stuff::C c(1, 42), cc(1, 42); D d; // commented lines invoke compilation failures std::cout << "a == aa: " << (a == aa) << std::endl; //std::cout << "a == b : " << (a == b ) << std::endl; //std::cout << "b == bb: " << (b == bb) << std::endl; //std::cout << "a == c : " << (a == c ) << std::endl; std::cout << "c == cc: " << (c == cc) << std::endl; std::cout << "d == c : " << (d == c ) << std::endl; } 
+3
source

So that you can try, put A in the namespace, create operator == as a non-member of the template in this namespace, and let ADL take care of this.

 #include <iostream> namespace stuff { class A { }; class B : public A {}; template <typename T> bool operator == (const T &lhs, const T &rhs) { std::cout << __PRETTY_FUNCTION__ << '\n'; return &lhs == &rhs; // <-- replace this with something real } } struct C {}; int main() { stuff::A a, aa; stuff::B b, bb; C c, cc; b == bb; aa == a; aa == cc; // error: no match for "operator==" stuff::A and C b == a; // error: no match for "operator==" stuff::B and stuff::A } 

Edit:. For your edited example, where you want the equality check to compare each part of the class with the other relevant part, the DyP clause might work. For instance:

 // same as before // ... class A { public: bool is_equal(const A &rhs) const { return i == rhs.i; } }; class B : public A { public: bool is_equal(const B &rhs) const { return A::is_equal(rhs) && (j == rhs.j); } }; template <typename T> bool operator == (const T &lhs, const T &rhs) { std::cout << __PRETTY_FUNCTION__ << '\n'; return lhs.is_equal(rhs); } 

Now compare this again in the code used:

 // ... bi = 1, bb.i = 1; bj = 1, bb.j = 42; cout << boolalpha << (b == bb) << '\n'; bj = 42; cout << (b == bb) << '\n'; ai = 2, aa.i = 3; cout << (aa == a) << '\n'; 

outputs:

 bool stuff::operator==(const T&, const T&) [with T = stuff::B] false bool stuff::operator==(const T&, const T&) [with T = stuff::B] true bool stuff::operator==(const T&, const T&) [with T = stuff::A] false 
+5
source

Why do you have an equality comparison in a class hierarchy? In many cases, this indicates a design problem, with classes that behave incorrectly as value types, but not like objects from a hierarchy.

+1
source

Source: https://habr.com/ru/post/1501975/


All Articles