#include <iostream>
#include <memory>
#include <vector>
class Root
{
public:
explicit Root(double bar) : Bar(bar) {}
// Base class must have a virtual destructor for deletion through
// the base pointer to work properly
virtual ~Root() {}
bool operator==(const Root& other) const
{
// Make sure the two types being compared are the same derived type
return (typeid(*this) == typeid(other)) &&
// Compare all state associated with the base class
(Bar == other.Bar) &&
// Dispatch comparison to the derived implementation to finish
// the comparison
isEqual(other);
}
private:
// Guaranteed to only be dispatched by operator== if 'other' is the
// same type as '*this'
virtual bool isEqual(const Root &other) const = 0;
double Bar;
};
class BranchA : public Root
{
public:
BranchA(double bar, double baz) : Root(bar), BazA(baz) {}
private:
virtual bool isEqual(const Root& other) const override
{
// static_cast is safe since the Base class guarantees it won't
// call this function unless 'other' and '*this' are the same type
const BranchA& branch = static_cast<const BranchA&>(other);
return (BazA == branch.BazA);
}
double BazA;
};
class BranchB : public Root
{
public:
BranchB(double bar, int baz, bool foo) : Root(bar), BazB(baz), Foo(foo) {}
private:
virtual bool isEqual(const Root& other) const override
{
// static_cast is safe since the Base class guarantees it won't
// call this function unless 'other' and '*this' are the same type
const BranchB& branch = static_cast<const BranchB&>(other);
return (BazB == branch.BazB) && (Foo == branch.Foo);
}
int BazB;
bool Foo;
};
void compare_loop(const Root &r, const std::vector<std::unique_ptr<Root>>& vec)
{
for (const auto& v : vec)
{
if (r == *v)
{
std::cout << "Equivalent\n";
}
else
{
std::cout << "Different\n";
}
}
}
int main()
{
BranchA root(1.0, 2.0);
std::vector<std::unique_ptr<Root>> branches;
branches.push_back(std::make_unique<BranchA>(root));
branches.push_back(std::make_unique<BranchA>(1.0, 1.0));
branches.push_back(std::make_unique<BranchB>(1.0, 2.0, true));
compare_loop(root, branches);
return 0;
}