1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
#pragma once
#include "compat/integer-types.hpp"
#include <type_traits>
#include <concepts>
#include <functional>
#include <Corrade/Containers/StringView.h>
namespace floormat {}
namespace floormat::entities {
template<typename T> using const_qualified = std::conditional_t<std::is_fundamental_v<T>, T, const T&>;
template<typename T> using ref_qualified = std::conditional_t<std::is_fundamental_v<T>, T, T&>;
template<typename T> using move_qualified = std::conditional_t<std::is_fundamental_v<T>, T, T&&>;
template<typename F, typename T, typename FieldType>
concept FieldReader_memfn = requires(const T x, F f) {
{ (x.*f)() } -> std::convertible_to<FieldType>;
};
template<typename F, typename T, typename FieldType>
concept FieldReader_ptr = requires(const T x, F f) {
{ x.*f } -> std::convertible_to<FieldType>;
};
template<typename F, typename T, typename FieldType>
concept FieldReader_function = requires(const T x, F f) {
{ f(x) } -> std::convertible_to<FieldType>;
};
template<typename F, typename T, typename FieldType>
concept FieldReader = requires {
requires FieldReader_memfn<F, T, FieldType> ||
FieldReader_ptr<F, T, FieldType> ||
FieldReader_function<F, T, FieldType>;
};
template<typename F, typename T, typename FieldType>
concept FieldWriter_memfn = requires(T x, move_qualified<FieldType> value, F f) {
{ (x.*f)(value) } -> std::same_as<void>;
};
template<typename F, typename T, typename FieldType>
concept FieldWriter_ptr = requires(T x, move_qualified<FieldType> value, F f) {
{ x.*f = value };
};
template<typename F, typename T, typename FieldType>
concept FieldWriter_function = requires(T x, move_qualified<FieldType> value, F f) {
{ f(x, value) } -> std::same_as<void>;
};
template<typename F, typename T, typename FieldType>
concept FieldWriter = requires {
requires FieldWriter_memfn<F, T, FieldType> ||
FieldWriter_ptr<F, T, FieldType> ||
FieldWriter_function<F, T, FieldType>;
};
template<typename Obj, typename Type, typename R>
struct read_field {
static 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)(); }
};
template<typename Obj, typename Type>
struct read_field<Obj, Type, Type Obj::*> {
static 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 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 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, FieldReader<Obj, FieldType> R, FieldWriter<Obj, FieldType> W>
struct field {
using Object = Obj;
using Type = FieldType;
using Reader = R;
using Writer = W;
StringView name;
Reader reader;
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); }
};
template<typename Obj>
struct entity {
template<typename FieldType>
struct Field {
template<FieldReader<Obj, FieldType> R, FieldWriter<Obj, FieldType> W>
struct make final : field<Obj, FieldType, R, W> {
consteval make(StringView name_, R r, W w) noexcept : field<Obj, FieldType, R, W>{name_, r, w} {}
};
template<FieldReader<Obj, FieldType> R, FieldWriter<Obj, FieldType> W>
make(StringView name, R r, W w) -> make<R, W>;
};
};
} // namespace floormat::entities
|