#include #include #include #include #include class Object; class Type { public: Type(Object *object) : object(object) { } Object *object; bool operator==(Type other); bool operator!=(Type other); enum class LesserOperatorStatus { Lesser = 0, Equal = 1, Object = 2, Error = 3 }; LesserOperatorStatus operator_lesser(const std::type_info &other_info); bool operator<(Type other); bool operator>(Type other); bool operator>=(Type other); bool operator<=(Type other); }; class Object { public: virtual ~Object() {}; Type type() { return Type(this); } }; bool Type::operator==(Type other) { return strcmp(typeid(*this->object).name(), typeid(*other.object).name()) == 0; /* std::type_info other_info = typeid(other.object); const __cxxabiv1::__si_class_type_info* other__si_class_type_info = dynamic_cast(&other_info); assert(other__si_class_type_info); return (typeid(*this->object) == *other__si_class_type_info->__base_type); */ } bool Type::operator!=(Type other) { return !this->operator==(other); } Type::LesserOperatorStatus Type::operator_lesser(const std::type_info &other_info) { Type::LesserOperatorStatus result = LesserOperatorStatus::Error; if (typeid(*this->object) == other_info) { result = LesserOperatorStatus::Equal; } else { const __cxxabiv1::__si_class_type_info* other__si_class_type_info = dynamic_cast(&other_info); if (!other__si_class_type_info) { assert(0); //printf("Assertion failed! this : %s, other : %s\n", typeid(*this->object).name(), other_info.name()); result = LesserOperatorStatus::Error; } else { const std::type_info *other_base_info = other__si_class_type_info->__base_type; if (typeid(*this->object) == *other_base_info) { result = LesserOperatorStatus::Lesser; } else if (typeid(Object) == *other_base_info) { result = LesserOperatorStatus::Object; } else { LesserOperatorStatus status = operator_lesser(*other_base_info); if (status == LesserOperatorStatus::Equal || status == LesserOperatorStatus::Lesser) { result = LesserOperatorStatus::Lesser; } else { result = status; } } } } return result; } bool Type::operator<(Type other) { const std::type_info *other_info = &typeid(*other.object); return this->operator_lesser(*other_info) == LesserOperatorStatus::Lesser; } bool Type::operator>(Type other) { return other.operator<(*this); } bool Type::operator>=(Type other) { return this->operator==(other) || this->operator>(other); } bool Type::operator<=(Type other) { return this->operator==(other) || this->operator<(other); } class Base : public Object { public: }; class Derived : public Base { public: }; class Leaf : public Derived { public: }; class Another : public Object { public: }; int main() { Object *objects[] = { new Base(), new Derived(), new Leaf(), new Another() }; size_t count = sizeof(objects) / sizeof(*objects); for (int i = 0; i < count; i++) { for (int j = 0; j < count; j++) { char trueStr[] = "\033[1;32mtrue\033[00m"; char falseStr[] = "\033[1;31mfalse\033[00m";; #define testoperator(op) printf("%s " #op " %s | %s\n", &typeid(*objects[i]).name()[1], &typeid(*objects[j]).name()[1], (objects[i]->type() op objects[j]->type()) ? trueStr : falseStr) testoperator(==); testoperator(!=); testoperator(<); testoperator(>); testoperator(<=); testoperator(>=); printf("\n"); } } };