#pragma once #include "util.hpp" #include #include namespace floormat::entities { struct erased_accessor final { using erased_reader_t = void; using erased_writer_t = void; using Object = void; using Value = void; const erased_reader_t* reader; const erased_writer_t* writer; StringView object_name, field_type_name; void(*read_fun)(const Object*, const erased_reader_t*, Value*); void(*write_fun)(Object*, const erased_writer_t*, Value*); constexpr erased_accessor(const erased_accessor&) = default; constexpr erased_accessor(erased_reader_t* reader, erased_writer_t * writer, StringView object_name, StringView field_type_name, void(*read_fun)(const Object*, const erased_reader_t*, Value*), void(*write_fun)(Object*, const erased_writer_t*, Value*)) : reader{reader}, writer{writer}, object_name{object_name}, field_type_name{field_type_name}, read_fun{read_fun}, write_fun{write_fun} {} template static constexpr bool check_name_static(); template constexpr bool check_name() const noexcept; template constexpr void assert_name() const noexcept; template void read_unchecked(const Obj& x, FieldType& value) const noexcept; template requires std::is_default_constructible_v FieldType read_unchecked(const Obj& x) const noexcept; template void write_unchecked(Obj& x, move_qualified value) const noexcept; template requires std::is_default_constructible_v FieldType read(const Obj& x) const noexcept; template void read(const Obj& x, FieldType& value) const noexcept; template void write(Obj& x, move_qualified value) const noexcept; constexpr bool can_write() const noexcept { return writer != nullptr; } }; template constexpr bool erased_accessor::check_name_static() { return !std::is_pointer_v && !std::is_reference_v && !std::is_pointer_v && !std::is_reference_v; } template constexpr bool erased_accessor::check_name() const noexcept { static_assert(check_name_static()); constexpr auto obj = name_of, field = name_of; return (obj.data() == object_name.data() && field.data() == field_type_name.data()) || obj == object_name && field == field_type_name; } template constexpr void erased_accessor::assert_name() const noexcept { fm_assert(check_name()); } template void erased_accessor::read_unchecked(const Obj& x, FieldType& value) const noexcept { static_assert(check_name_static()); read_fun(&x, reader, &value); } template requires std::is_default_constructible_v FieldType erased_accessor::read_unchecked(const Obj& x) const noexcept { static_assert(check_name_static()); FieldType value; read_unchecked(x, value); return value; } template void erased_accessor::write_unchecked(Obj& x, move_qualified value) const noexcept { static_assert(check_name_static()); write_fun(&x, writer, &value); } template requires std::is_default_constructible_v FieldType erased_accessor::read(const Obj& x) const noexcept { assert_name(); return read_unchecked(x); } template void erased_accessor::read(const Obj& x, FieldType& value) const noexcept { assert_name(); read_unchecked(x, value); } template void erased_accessor::write(Obj& x, move_qualified value) const noexcept { assert_name(); write_unchecked(x, value); } } // namespace floormat::entities