#pragma once #include "util.hpp" #include "compat/function2.hpp" #include "compat/assert.hpp" #include #include namespace floormat::entities { 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) { requires std::is_reference_v; requires !std::is_const_v>; { x.*f } -> std::convertible_to; { 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 || std::same_as; }; } // namespace floormat::entities namespace floormat::entities::detail { template R> struct read_field { static constexpr Type read(const Obj& x, R r) { return r(x); } }; template struct read_field { static constexpr Type read(const Obj& x, Type (Obj::*r)() const) { return (x.*r)(); } }; template struct read_field { static constexpr Type read(const Obj& x, const Type Obj::*r) { return x.*r; } }; template struct read_field { static constexpr Type read(const Obj& x, Type Obj::*r) { return x.*r; } }; template struct read_field) const>> { template static constexpr Type read(const Obj& x, F&& fun) { return fun(x); } }; template W> struct write_field { static constexpr void write(Obj& x, W w, move_qualified value) { w(x, 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 constexpr void write(Obj& x, FieldType Obj::* w, move_qualified value) { x.*w = value; } }; template struct write_field) const>> { template static constexpr void write(Obj& x, F&& fun, move_qualified value) { fun(x, value); } }; template struct write_field { static constexpr void write(Obj&, std::nullptr_t, move_qualified) { fm_abort("no writing for this accessor"); } }; } // namespace floormat::entities::detail