From 65b3b6603e8761a9629f7da19c352384bad2d4bf Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 16 Nov 2022 15:46:51 +0100 Subject: entity: add type erasure support --- src/entity.hpp | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/entity.hpp b/src/entity.hpp index a5c9aa90..f1c38397 100644 --- a/src/entity.hpp +++ b/src/entity.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -138,6 +139,16 @@ constexpr CORRADE_ALWAYS_INLINE bool find_in_tuple(F&& fun, Tuple&& tuple) } // namespace detail +struct erased_accessors final { + struct erased_reader_t; + struct erased_writer_t; + const erased_reader_t* reader; + const erased_writer_t* writer; + const char *object_type, *field_type; + void(*read_fun)(const void*, const erased_reader_t*, void*); + void(*write_fun)(void*, const erased_writer_t*, void*); +}; + struct EntityBase {}; template @@ -161,15 +172,37 @@ struct Entity final : EntityBase { using Writer = W; StringView name; - [[no_unique_address]] Reader reader; - [[no_unique_address]] Writer writer; + [[no_unique_address]] R reader; + [[no_unique_address]] W writer; constexpr field(const field&) = default; constexpr field& operator=(const field&) = default; - constexpr decltype(auto) read(const Obj& x) const { return detail::read_field::read(x, reader); } - constexpr void write(Obj& x, move_qualified v) const { detail::write_field::write(x, writer, v); } - - constexpr field(StringView name, Reader r, Writer w) noexcept : name{name}, reader{r}, writer{w} {} + static constexpr decltype(auto) read(const R& reader, const Obj& x) { return detail::read_field::read(x, reader); } + static constexpr void write(const W& writer, Obj& x, move_qualified v) { detail::write_field::write(x, writer, v); } + constexpr decltype(auto) read(const Obj& x) const { return read(reader, x); } + constexpr void write(Obj& x, move_qualified value) const { write(writer, x, value); } + consteval field(StringView name, R r, W w) noexcept : name{name}, reader{r}, writer{w} {} + + erased_accessors accessors() const { + using reader_t = typename erased_accessors::erased_reader_t; + using writer_t = typename erased_accessors::erased_writer_t; + return erased_accessors { + reinterpret_cast(&reader), reinterpret_cast(&writer), + typeid(Obj).name(), typeid(Type).name(), + [](const void* obj, const reader_t* reader, void* value) { + const auto& obj_ = *reinterpret_cast(obj); + const auto& reader_ = *reinterpret_cast(reader); + auto& value_ = *reinterpret_cast(value); + value_ = read(reader_, obj_); + }, + [](void* obj, const writer_t* writer, void* value) { + auto& obj_ = *reinterpret_cast(obj); + const auto& writer_ = *reinterpret_cast(writer); + auto&& value_ = std::move(*reinterpret_cast(value)); + write(writer_, obj_, value_); + }, + }; + } }; template R, FieldWriter W> -- cgit v1.2.3