#pragma once #include "compat/integer-types.hpp" #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 using const_qualified = std::conditional_t, T, const T&>; template using ref_qualified = std::conditional_t, T, T&>; template using move_qualified = std::conditional_t, T, T&&>; template concept FieldReader_memfn = requires(const T x, F f) { { (x.*f)() } -> std::convertible_to; }; template concept FieldReader_ptr = requires(const T x, F f) { { x.*f } -> std::convertible_to; }; template concept FieldReader_function = requires(const T x, F f) { { f(x) } -> std::convertible_to; }; template concept FieldReader = requires { requires FieldReader_memfn || FieldReader_ptr || FieldReader_function; }; template concept FieldWriter_memfn = requires(T x, move_qualified value, F f) { { (x.*f)(value) } -> std::same_as; }; template concept FieldWriter_ptr = requires(T x, move_qualified value, F f) { { x.*f = value }; }; template concept FieldWriter_function = requires(T x, move_qualified value, F f) { { f(x, value) } -> std::same_as; }; template concept FieldWriter = requires { requires FieldWriter_memfn || FieldWriter_ptr || FieldWriter_function; }; template struct read_field { static 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)(); } }; template struct read_field { static 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 struct write_field)> { static 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 R, FieldWriter W> struct field { using Object = Obj; using Type = FieldType; using Reader = R; using Writer = W; StringView name; [[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); } }; template struct entity final { template struct Field { template R, FieldWriter W> static consteval auto make(StringView name, R r, W w) noexcept { return field { name, r, w }; } }; }; template struct assoc final { template using Types = std::tuple; consteval assoc(Xs&&... xs) { } private: template struct cell { Key key; T value; }; std::tuple...> _tuple; }; } // namespace floormat::entities