summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/entity.hpp101
-rw-r--r--test/entity.cpp34
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 <Corrade/Containers/StringView.h>
#include <concepts>
+#include <compare>
#include <type_traits>
-#include <tuple>
-#include <utility>
-#include <algorithm>
-
-#include <Corrade/Containers/StringView.h>
namespace floormat {}
namespace floormat::entities {
template<typename T> struct pass_by_value : std::bool_constant<std::is_fundamental_v<T>> {};
-template<typename T> constexpr inline bool pass_by_value_v = pass_by_value<T>::value;
template<> struct pass_by_value<StringView> : std::true_type {};
+template<typename T> constexpr inline bool pass_by_value_v = pass_by_value<T>::value;
template<typename T> using const_qualified = std::conditional_t<pass_by_value_v<T>, T, const T&>;
template<typename T> using ref_qualified = std::conditional_t<pass_by_value_v<T>, T, T&>;
@@ -64,37 +61,41 @@ concept FieldWriter = requires {
FieldWriter_function<F, T, FieldType>;
};
-template<typename Obj, typename Type, typename R>
+namespace detail {
+
+template<typename Obj, typename Type, FieldReader<Obj, Type> 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<typename Obj, typename Type>
struct read_field<Obj, Type, Type (Obj::*)() const> {
- 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<typename Obj, typename Type>
struct read_field<Obj, Type, Type Obj::*> {
- 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<typename Obj, typename FieldType, typename Writer> struct write_field {
- static void write(Obj& x, Writer w, move_qualified<FieldType> value) { w(x, value); }
+template<typename Obj, typename FieldType, FieldWriter<Obj, FieldType> W> struct write_field {
+ static constexpr void write(Obj& x, W w, move_qualified<FieldType> value) { w(x, value); }
};
-template<typename Obj, typename Type>
-struct write_field<Obj, Type, void(Obj::*)(move_qualified<Type>)> {
- static void write(Obj& x, void(Obj::*w)(move_qualified<Type>), move_qualified<Type> value) { (x.*w)(value); }
+template<typename Obj, typename FieldType>
+struct write_field<Obj, FieldType, void(Obj::*)(move_qualified<FieldType>)> {
+ static constexpr void write(Obj& x, void(Obj::*w)(move_qualified<FieldType>), move_qualified<FieldType> value) { (x.*w)(value); }
};
-template<typename Obj, typename Type>
-struct write_field<Obj, Type, Type Obj::*> {
- static void write(Obj& x, Type Obj::* w, move_qualified<Type> value) { x.*w = value; }
+template<typename Obj, typename FieldType>
+struct write_field<Obj, FieldType, FieldType Obj::*> {
+ static constexpr void write(Obj& x, FieldType Obj::* w, move_qualified<FieldType> value) { x.*w = value; }
};
-template<typename Obj, typename FieldType, FieldReader<Obj, FieldType> R, FieldWriter<Obj, FieldType> W>
-struct field {
+} // namespace detail
+
+template<typename Obj, typename FieldType, typename R, typename W>
+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<Obj, FieldType, R>::read(x, reader); }
- void write(Obj& x, move_qualified<FieldType> v) const { write_field<Obj, FieldType, W>::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<Obj, FieldType, R>::read(x, reader); }
+ constexpr void write(Obj& x, move_qualified<FieldType> v) const { detail::write_field<Obj, FieldType, W>::write(x, writer, v); }
+
+protected:
+ constexpr field_(StringView name, Reader r, Writer w) noexcept : name{name}, reader{r}, writer{w} {}
};
template<typename Obj>
-struct entity final {
+requires std::is_same_v<Obj, std::decay_t<Obj>>
+struct Entity final {
template<typename FieldType>
- struct Field {
+ requires std::is_same_v<Obj, std::decay_t<Obj>>
+ struct type {
+ template<FieldReader<Obj, FieldType> R, FieldWriter<Obj, FieldType> W>
+ struct field final : field_<Obj, FieldType, R, W> {
+ constexpr field(StringView field_name, R r, W w) : field_<Obj, FieldType, R, W>{field_name, r, w} {}
+ };
+
template<FieldReader<Obj, FieldType> R, FieldWriter<Obj, FieldType> W>
- static consteval auto make(StringView name, R r, W w) noexcept {
- return field<Obj, FieldType, R, W> { name, r, w };
- }
+ field(StringView name, R r, W w) -> field<R, W>;
};
};
-template<typename Key, typename KeyT, typename... Xs>
-struct assoc final {
- template<typename T> using Types = std::tuple<Xs...>;
- consteval assoc(Xs&&... xs) {
-
- }
-
-private:
- template<typename T> struct cell { Key key; T value; };
- std::tuple<cell<Xs>...> _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<erased_field_type> struct type_of_erased_field;
+template<typename T> struct erased_field_type_v_ : std::integral_constant<erased_field_type, erased_field_type::none> {};
+
+#define FM_ERASED_FIELD_TYPE(TYPE, ENUM) \
+ template<> struct erased_field_type_v_<TYPE> : std::integral_constant<erased_field_type, erased_field_type::ENUM> {}; \
+ template<> struct type_of_erased_field<erased_field_type::ENUM> { 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<TestAccessors>;
+static constexpr auto m_foo = entity::type<int>::field{"foo"_s, &TestAccessors::foo, &TestAccessors::foo};
+static constexpr auto m_bar = entity::type<int>::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<int>::field("baz"_s, r_baz, w_baz);
namespace floormat {
-using namespace floormat::entities;
-
static void test_accessors()
{
- using Test = ::TestAccessors;
- using Entity = entity<Test>;
- constexpr auto m_foo = Entity::Field<int>::make("foo"_s, &Test::foo, &Test::foo);
- constexpr auto m_bar = Entity::Field<int>::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<int>::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();