From 8f0b22e3fe082c2b5c75a7fe3435f56a38cbc5a2 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Mon, 14 Nov 2022 13:59:57 +0100 Subject: entity: more work --- src/entity.hpp | 101 ++++++++++++++++++++++++++++++++++---------------------- test/entity.cpp | 34 +++++++------------ 2 files changed, 74 insertions(+), 61 deletions(-) diff --git a/src/entity.hpp b/src/entity.hpp index b46fefcc..2bf52970 100644 --- a/src/entity.hpp +++ b/src/entity.hpp @@ -1,20 +1,17 @@ #pragma once #include "compat/integer-types.hpp" +#include #include +#include #include -#include -#include -#include - -#include namespace floormat {} namespace floormat::entities { template struct pass_by_value : std::bool_constant> {}; -template constexpr inline bool pass_by_value_v = pass_by_value::value; template<> struct pass_by_value : std::true_type {}; +template constexpr inline bool pass_by_value_v = pass_by_value::value; template using const_qualified = std::conditional_t, T, const T&>; template using ref_qualified = std::conditional_t, T, T&>; @@ -64,37 +61,41 @@ concept FieldWriter = requires { FieldWriter_function; }; -template +namespace detail { + +template R> struct read_field { - static Type read(const Obj& x, R r) { return r(x); } + static constexpr Type read(const Obj& x, R r) { return r(x); } }; template struct read_field { - static Type read(const Obj& x, Type (Obj::*r)() const) { return (x.*r)(); } + static constexpr Type read(const Obj& x, Type (Obj::*r)() const) { return (x.*r)(); } }; template struct read_field { - static Type read(const Obj& x, Type Obj::*r) { return x.*r; } + static constexpr Type read(const Obj& x, Type Obj::*r) { return x.*r; } }; -template struct write_field { - static void write(Obj& x, Writer w, move_qualified value) { w(x, value); } +template W> struct write_field { + static constexpr void write(Obj& x, W w, move_qualified value) { w(x, value); } }; -template -struct write_field)> { - static void write(Obj& x, void(Obj::*w)(move_qualified), move_qualified value) { (x.*w)(value); } +template +struct write_field)> { + static constexpr void write(Obj& x, void(Obj::*w)(move_qualified), move_qualified value) { (x.*w)(value); } }; -template -struct write_field { - static void write(Obj& x, Type Obj::* w, move_qualified value) { x.*w = value; } +template +struct write_field { + static constexpr void write(Obj& x, FieldType Obj::* w, move_qualified value) { x.*w = value; } }; -template R, FieldWriter W> -struct field { +} // namespace detail + +template +struct field_ { using Object = Obj; using Type = FieldType; using Reader = R; @@ -104,32 +105,54 @@ struct field { [[no_unique_address]] Reader reader; [[no_unique_address]] Writer writer; - constexpr field(StringView name, Reader r, Writer w) noexcept : name{name}, reader{r}, writer{w} {} - decltype(auto) read(const Obj& x) const { return read_field::read(x, reader); } - void write(Obj& x, move_qualified v) const { write_field::write(x, writer, v); } + 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); } + +protected: + constexpr field_(StringView name, Reader r, Writer w) noexcept : name{name}, reader{r}, writer{w} {} }; template -struct entity final { +requires std::is_same_v> +struct Entity final { template - struct Field { + requires std::is_same_v> + struct type { + template R, FieldWriter W> + struct field final : field_ { + constexpr field(StringView field_name, R r, W w) : field_{field_name, r, w} {} + }; + template R, FieldWriter W> - static consteval auto make(StringView name, R r, W w) noexcept { - return field { name, r, w }; - } + field(StringView name, R r, W w) -> field; }; }; -template -struct assoc final { - template using Types = std::tuple; - consteval assoc(Xs&&... xs) { - - } - -private: - template struct cell { Key key; T value; }; - std::tuple...> _tuple; -}; +enum class erased_field_type : std::uint32_t { + none, + string, + u8, u16, u32, u64, s8, s16, s32, s64, + user_type_start, + MAX = (std::uint32_t)-1, +}; + +template struct type_of_erased_field; +template struct erased_field_type_v_ : std::integral_constant {}; + +#define FM_ERASED_FIELD_TYPE(TYPE, ENUM) \ + template<> struct erased_field_type_v_ : std::integral_constant {}; \ + template<> struct type_of_erased_field { using type = TYPE; } +FM_ERASED_FIELD_TYPE(std::uint8_t, u8); +FM_ERASED_FIELD_TYPE(std::uint16_t, u16); +FM_ERASED_FIELD_TYPE(std::uint32_t, u32); +FM_ERASED_FIELD_TYPE(std::uint64_t, u64); +FM_ERASED_FIELD_TYPE(std::int8_t, s8); +FM_ERASED_FIELD_TYPE(std::int16_t, s16); +FM_ERASED_FIELD_TYPE(std::int32_t, s32); +FM_ERASED_FIELD_TYPE(std::int64_t, s64); +FM_ERASED_FIELD_TYPE(StringView, string); +#undef FM_ERASED_FIELD_TYPE } // namespace floormat::entities diff --git a/test/entity.cpp b/test/entity.cpp index 50d5e34b..80032b6f 100644 --- a/test/entity.cpp +++ b/test/entity.cpp @@ -2,34 +2,29 @@ #include "compat/assert.hpp" #include "src/entity.hpp" -namespace { +using namespace floormat; +using namespace floormat::entities; struct TestAccessors { - int foo = 111; int bar() const { return _bar; } void set_bar(int value) { _bar = value; } - int _baz = 333; -private: - int _bar = 222; + int foo; + int _bar; + int _baz; }; -} // namespace +using entity = Entity; +static constexpr auto m_foo = entity::type::field{"foo"_s, &TestAccessors::foo, &TestAccessors::foo}; +static constexpr auto m_bar = entity::type::field{"bar"_s, &TestAccessors::bar, &TestAccessors::set_bar}; +static constexpr auto r_baz = [](const TestAccessors& x) { return x._baz; }; +static constexpr auto w_baz = [](TestAccessors& x, int v) { x._baz = v; }; +static constexpr auto m_baz = entity::type::field("baz"_s, r_baz, w_baz); namespace floormat { -using namespace floormat::entities; - static void test_accessors() { - using Test = ::TestAccessors; - using Entity = entity; - constexpr auto m_foo = Entity::Field::make("foo"_s, &Test::foo, &Test::foo); - constexpr auto m_bar = Entity::Field::make("bar"_s, &Test::bar, &Test::set_bar); - constexpr auto r_baz = [](const Test& x) { return x._baz; }; - constexpr auto w_baz = [](Test& x, int v) { x._baz = v; }; - constexpr auto m_baz = Entity::Field::make("baz"_s, r_baz, w_baz); - - auto x = Test{}; + auto x = TestAccessors{111, 222, 333}; { auto a = m_foo.read(x), b = m_bar.read(x), c = m_baz.read(x); @@ -45,11 +40,6 @@ static void test_accessors() } } -static void test_() -{ - -} - void test_app::test_entity() { test_accessors(); -- cgit v1.2.3