-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathReflectionFunction.h
More file actions
289 lines (257 loc) · 11.3 KB
/
Copy pathReflectionFunction.h
File metadata and controls
289 lines (257 loc) · 11.3 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
#pragma once
#include "TypeTrait.h"
#include "TypeDefinition.h" // CT11-c: 종전 MetaUtility.h 경유 전이 include를 직접
#include <typeindex> // CT11-c: 흡수된 ToString(std::type_index)의 자급
#include "ReflectionType.h"
#include "ReflectionRegister.h"
#include "LogSystem.h"
#include "HashingString.h"
#include "MetaSchema.h" // 열거형 표(meta::enum_entries) — magic_enum 대체(CT9-b)
namespace Meta
{
// 타입의 런타임 Type 테이블 단일 창구 — 정의는 ReflectionMeta.h.
// CT9: 타입은 reflect() 레시피(또는 meta::of<T> 외부 서술)만 선언하고, 이
// 함수가 어댑터(meta::adapt)로 런타임 Type을 공급한다. 레거시 Reflect()
// 폴백 가지는 정의 잔존 0건 증명 후 제거됐다(CT8).
template<class T>
const Type& TypeOf();
template<typename T>
static inline void Register()
{
const Type& type = TypeOf<T>();
Registry::GetInstance()->Register(type);
// CT11: FactoryRegistry 등록 은퇴 — 팩토리는 adapt가 Type에 직접 채운다.
// CT7: VectorFactory/Invoker 등록 은퇴 — 레거시 워크 전용이었다.
}
static inline const Type* Find(std::string_view name)
{
// CT11-b: view 그대로 전달 — .data()는 NUL 비보장 view에서 잠재
// 오독이었고, std::string 생성(할당)도 사라졌다.
return Registry::GetInstance()->Find(name);
}
// FindEnum(이름 키 조회)은 열거형 점검(8-17)에서 삭제 — 소비자 전원이
// Property::enumType 직접 참조로 전환됐다(이름 매칭 실패 여지 자체가 소멸).
static inline const Type* Find(size_t typeID)
{
return Registry::GetInstance()->Find(typeID);
}
// ── CT11-c: MetaUtility.h 흡수 — 소비자가 이 파일 하나뿐이었다. 사강
// 5종(Hash·GetMemberOffset·IsVectorType·ExtractVectorElementType·
// GetVectorElementTypeName)은 삭제. ToString은 typeid 기반 런타임 이름
// (Property::typeName의 정본 — 컴파일타임 meta::type_name_of와 별개 계보,
// 골든 파리티가 이 표기에 걸려 있어 통합하지 않는다).
template<typename T>
inline std::string ToString()
{
std::string name = std::type_index(typeid(T)).name();
const std::string struct_prefix = "struct ";
const std::string class_prefix = "class ";
const std::string enum_prefix = "enum ";
if (name.find(struct_prefix) == 0)
name = name.substr(struct_prefix.size());
else if (name.find(class_prefix) == 0)
name = name.substr(class_prefix.size());
else if (name.find(enum_prefix) == 0)
name = name.substr(enum_prefix.size());
size_t pointerPos = name.find(" *");
if (pointerPos != std::string::npos)
{
name = name.substr(0, pointerPos);
}
return name;
}
inline std::string RemoveObjectPrefix(const std::string& name)
{
const std::string object_prefix = "class ";
const std::string struct_prefix = "struct ";
const std::string enum_prefix = "enum ";
if (name.find(object_prefix) == 0)
return name.substr(object_prefix.size());
else if (name.find(struct_prefix) == 0)
return name.substr(struct_prefix.size());
else if (name.find(enum_prefix) == 0)
return name.substr(enum_prefix.size());
return name;
}
inline static bool IsSharedPtr(std::string_view tn)
{
return tn.find("std::shared_ptr<") != std::string_view::npos;
}
inline static bool IsWeakPtr(std::string_view tn)
{
return tn.find("std::weak_ptr<") != std::string_view::npos;
}
inline static bool IsRawPtr(std::string_view tn)
{
return tn.size() && tn.back() == '*';
}
inline static std::string ExtractPointee(std::string_view tn)
{
// "std::shared_ptr<Foo>" -> "Foo" · "std::weak_ptr<Foo>" -> "Foo" · "Foo*" -> "Foo"
if (IsSharedPtr(tn) || IsWeakPtr(tn))
{
auto b = tn.find('<'); auto e = tn.rfind('>');
return std::string(tn.substr(b + 1, e - b - 1));
}
if (IsRawPtr(tn))
{
return std::string(tn.substr(0, tn.size() - 1));
}
return std::string(tn);
}
// CT9-b: magic_enum 은퇴 — 자급 표(meta::enum_entries, __FUNCSIG__ 범위
// 스캔·동일 범위/순서)를 레거시 EnumValue 표로 투영한다. 이름은 정적
// 물질화라 NUL 종단(콘솔의 문자열 비교 전제).
template <typename Enum>
const EnumType& create_enum_type()
{
static const auto values = []
{
constexpr auto& src = meta::enum_entries<Enum>;
std::array<EnumValue, src.size()> out{};
for (size_t i = 0; i < src.size(); ++i)
{
out[i] = EnumValue{ src[i].name.data(), static_cast<int>(src[i].value) };
}
return out;
}();
static const EnumType enumType
{
meta::type_name_of<Enum>().data(),
std::span<const EnumValue>(values.data(), values.size())
};
return enumType;
}
// CT10 감사 수축: 벡터 특수 분기 3종(포인터/shared_ptr/객체 원소)이
// 산출하던 필드(isVector·elementType*·createVectorIterator·isPointer·
// offset·typeInfo·getter)는 전부 소비 0으로 판명되어 삭제 — 남은 산출은
// name·typeName·setter·typeID뿐이라 세 분기가 구별 불가능해졌고, 단일
// 제네릭 경로로 접힌다. shared_ptr 이름 보정만이 분기의 생존자다
// (콘솔·DrawMethods가 읽는 typeName을 살린다).
template<typename ClassT, typename T>
Property MakePropertyImpl(const char* name, T ClassT::* member)
{
std::string typeStr = ToString<T>();
HashedGuid typeID = TypeTrait::GUIDCreator::GetTypeID<T>();
if constexpr (is_shared_ptr_v<T>)
{
// 타입 이름은 가리키는 대상의 이름이어야 한다.
// 원시 포인터는 ToString이 "Material *"에서 " *"를 떼어 "Material"을 주지만,
// shared_ptr은 "std::shared_ptr<class Material>"이 그대로 남는다.
typeStr = RemoveObjectPrefix(ExtractPointee(typeStr));
}
if constexpr (Meta::HasReflection<std::remove_cvref_t<T>>)
{
Meta::Register<std::remove_cvref_t<T>>();
}
return
{
name,
typeStr,
[member, name](void* instance, std::any value)
{
// K2 스테이지 A 함정(실측): vector<std::unique_ptr<Component>>
// 같은 필드는 std::any_cast<T>가 T의 복사 생성을 요구하는데,
// std::is_copy_constructible_v<vector<unique_ptr<X>>>는 vector의
// 복사 생성자 선언이 원소 타입과 무관하게 항상 존재해 true로
// 오판된다 — 여기서 그대로 두면 컴파일이 깨진다. 원소까지
// 내려가 판정하는 IsCopyableForProperty<T>()로 이 분기 자체를
// 인스턴스화 대상에서 뺀다(콘솔 세터는 애초에 이런 필드를
// 지원한 적이 없다 — m_components는 ComponentFactory 몫).
if constexpr (IsCopyableForProperty<T>())
{
static_cast<ClassT*>(instance)->*member = std::any_cast<T>(value);
}
else
{
Debug->LogWarning(std::string("MakePropertyImpl: 콘솔 세터가 지원하지 않는 타입(복사 불가) - ") + name);
}
},
typeID,
};
}
template<typename ClassT, typename EnumT>
std::enable_if_t<std::is_enum_v<EnumT>, Property>
MakeEnumPropertyImpl(const char* name, EnumT ClassT::* member)
{
Property prop
{
name,
ToString<EnumT>(),
[member](void* instance, std::any anyValue) {
int intValue = std::any_cast<int>(anyValue);
static_cast<ClassT*>(instance)->*member = static_cast<EnumT>(intValue);
},
TypeTrait::GUIDCreator::GetTypeID<EnumT>(),
};
// 여기서 EnumT를 정적으로 알고 있으므로 이름 키 등록소가 필요 없다 —
// 콘솔/인스펙터의 enum 항목 소비는 이 포인터 하나로 끝난다.
prop.enumType = &create_enum_type<EnumT>();
return prop;
}
template<typename ClassT, typename T>
Property MakeProperty(const char* name, T ClassT::* member)
{
if constexpr (std::is_enum_v<T>)
{
return MakeEnumPropertyImpl(name, member);
}
else
{
return MakePropertyImpl(name, member);
}
}
template<typename ClassT, typename Ret, typename... Args, std::size_t... Is>
Method MakeMethodImpl(
const char* name,
Ret(ClassT::* method)(Args...),
std::index_sequence<Is...>,
const std::vector<std::string>& paramNames)
{
std::vector<MethodParameter> params = {
MethodParameter{
(Is < paramNames.size() ? paramNames[Is] : ("arg" + std::to_string(Is))),
ToString<Args>(),
TypeTrait::GUIDCreator::GetTypeID<Args>()
}...
};
return
{
name,
[method](void* instance, const std::vector<std::any>& args) -> std::any
{
if (args.size() != sizeof...(Args))
throw std::runtime_error("Argument count mismatch");
auto call = [=]<std::size_t... I>(std::index_sequence<I...>) -> std::any
{
if constexpr (std::is_void_v<Ret>)
{
(static_cast<ClassT*>(instance)->*method)(
std::any_cast<std::remove_reference_t<Args>>(args[I])...
);
return {};
}
else
{
return (static_cast<ClassT*>(instance)->*method)(
std::any_cast<std::remove_reference_t<Args>>(args[I])...
);
}
};
return call(std::index_sequence_for<Args...>{});
},
std::move(params)
};
}
template<typename ClassT, typename Ret, typename... Args>
Method MakeMethod(const char* name, Ret(ClassT::* method)(Args...), const std::vector<std::string>& paramNames = {})
{
return MakeMethodImpl(name, method, std::index_sequence_for<Args...>{}, paramNames);
}
// InvokeMethodByMetaName은 CT2에서 삭제 — 호출처 0건. 문자열 메서드
// 디스패치의 옛 소비자(키프레임 이벤트·입력 액션)는 CoreCLR 은퇴(9-4)에서
// 관리 측으로 이관됐다. Method 체계 자체는 인스펙터 DrawMethods가 쓰므로 유지.
// MakePropChangeCommand는 CT10 감사에서 삭제 — 호출자 0건(레거시 인스펙터
// 체인과 동반 사망). 활성 Undo 경로였던 MakeCustomChangeCommand는 호출자가
// 전부 에디터 UI라 UndoManager와 함께 ReflectionUndo.h(에디터 층)로 갔다.
}