Created
March 9, 2018 23:20
-
-
Save SeijiEmery/d4979cb5bfff7d525568b3c24462feb5 to your computer and use it in GitHub Desktop.
c++ overengineering
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class TypeInfo; | |
class InputRange; | |
class OutputRange; | |
class IORange; | |
class IObject { | |
public: | |
virtual ~IObject {} | |
virtual const TypeInfo& typeinfo () = 0; | |
virtual void repr (IStringWriter&) const = 0; | |
virtual void visit (IObjectVisitor&) const = 0; | |
virtual void serialize (ISerializer&) const = 0; | |
virtual void deserialize (IDeserializer&) const = 0; | |
}; | |
template <typename T> | |
class DefaultObjectRepr : public IObject { | |
void repr (IStringWriter& writer) const override { | |
T& self = static_cast<T&>(*this); | |
writer % "[" % self.typeinfo().name() % " ("; | |
bool first = true; | |
self.typeinfo().memberObjects(self).each([&](IObject& object) { | |
if (object.typeinfo().flags().reprable()) { | |
if (!first) { writer % " "; } else { first = false; } | |
member.getFromThis(this).repr(writer); | |
} | |
}); | |
writer % ")]"; | |
} | |
}; | |
template <typename T> | |
class DefaultObjectSerializer : public IObject { | |
void serialize (ISerializer& serializer) const override { | |
T& self = static_cast<T&>(*this); | |
serializer.beginObject(self); | |
self.typeinfo().memberObjects(self).each([&](IObject& object) { | |
if (object.typeinfo().flags().serializable()) { | |
object.serialize(serializer); | |
} | |
}); | |
serializer.endObject(self); | |
} | |
void deserialize (IDeserializer& deserializer) const override { | |
T& self = static_cast<T&>(*this); | |
deserializer.beginObject(self); | |
self.typeinfo().memberObjects(self).each([&](IObject& object) { | |
if (object.typeinfo().flags().serializable()) { | |
object.deserialize(deserializer); | |
} | |
}); | |
deserializer.endObject(self); | |
} | |
}; | |
template <typename T> | |
class DefaultObjectVisitor : public IObject { | |
void visit (IObjectVisitor& visitor) const override { | |
T& self = static_cast<T&>(*this); | |
visitor.enter(self); | |
visitor.apply(self.typeinfo().getMemberObjects(self)); | |
visitor.exit (self); | |
} | |
}; | |
namespace detail { | |
class IObjectHasher : public IObjectVisitor, NonCopyable { | |
private: | |
IHash* hash; | |
public: | |
IObjectHasher (decltype(hash) hash) : hash(hash) {} | |
void enter (IObject& object) override { | |
auto bytes = object.typeinfo().memRange(object); | |
hash += bytes; | |
} | |
void apply (IObject& object) { | |
if (object.typeinfo().flags().hashable()) { | |
object.visit(*this); | |
} | |
} | |
}; | |
} // namespace detail | |
template <typename HashFunction = DefaultHashFunction> | |
hash_t hashOf (IObject& object) { | |
HashFunction hashFunction; | |
detail::IObjectHasher hasher { &hashFunction }; | |
object.visit(hasher); | |
return hashFunction.hash(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment