#include <iostream>
#include <typeinfo>
using namespace std;

struct A {
	virtual bool operator==(const A &other) const = 0;
};

template<typename Base, typename Derived>
struct PolymorphicComparable : public Base {
    bool operator==(const Base &other) const {
    	if (typeid(other) != typeid(Derived))
    		return false;
    	const Derived & a = static_cast<const Derived&>(*this);
    	const Derived & b = static_cast<const Derived&>(other);
    	return a == b; // call Derived::operator==(Derived)
    }
};

struct A1 : public PolymorphicComparable<A,A1>
{
    int i;
    A1(int i) : i(i) {}
    
    bool operator==(const A1 &other) const {
    	return i == other.i;
    }
};

struct A2 : public PolymorphicComparable<A,A2>
{
    float f;
    A2(float f) : f(f) {}
    
    bool operator==(const A2 &other) const {
    	return f == other.f;
    }
};


int main() {
	A * a = new A1(5);
	A * b = new A1(2);
	A * c = new A2(7.6);
	A * d = new A2(7.6);
	
	// Comparing objects of same dynamic type:
	cout << (*a == *b) << endl;
	cout << (*c == *d) << endl;
	
	// Comparing objects of different dynamic types:
	cout << (*a == *c) << endl;
	
	return 0;
}