Skip to content

Instantly share code, notes, and snippets.

@SeijiEmery
Created March 9, 2018 23:20
Show Gist options
  • Save SeijiEmery/d4979cb5bfff7d525568b3c24462feb5 to your computer and use it in GitHub Desktop.
Save SeijiEmery/d4979cb5bfff7d525568b3c24462feb5 to your computer and use it in GitHub Desktop.
c++ overengineering
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