CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
Type.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2022 Rogiel Sulzbach. All rights reserved.
6//
7
8#pragma once
9
10#include "Forward.hpp"
11
12#include "TypeName.hpp"
13#include "TypeInfo.hpp"
14
17
21
22namespace CeresEngine {
23
24 namespace internal {
25 struct ConvertFunctionBase;
26 } // namespace internal
27
30
32 class Type final {
33 private:
35 const TypeInfo* mTypeInfo = nullptr;
36
37 public:
39 explicit Type(const TypeInfo& typeInfo) : mTypeInfo(&typeInfo) {}
40
42 explicit Type(StringView name) noexcept;
43
46 [[nodiscard]] static Type fromName(StringView name) noexcept;
47
49 explicit Type(TypeID typeID) noexcept;
50
53 [[nodiscard]] static Type fromID(TypeID id) noexcept;
54
55 public:
61
65
68
72
76
81
82 public: // Associated types
84 [[nodiscard]] bool isDecayed() const noexcept { return isValid() && (getTypeID() == getDecayTypeID()); }
85
90
93
96
99
100 public: // Type flags
103
106
109
112
115
118
121
124
127
130
133
134 public: // Meta interface
136 template<typename T> [[nodiscard]] bool is() const;
137
140
145
150
151 public: // Type conversion
158
160 [[nodiscard]] bool compatible(const Type& other) const noexcept { return compatible(*this, other); }
161
163 template<typename T> [[nodiscard]] bool compatible() const noexcept;
164
168
171
174
180
183
184 public:
188
190 void destruct(void* instance) const;
191
192 public:
194 [[nodiscard]] bool isValid() const noexcept { return (mTypeInfo != nullptr); }
195
197 [[nodiscard]] explicit operator bool() const noexcept { return isValid(); }
198
200 [[nodiscard]] friend bool operator==(const Type& type, std::nullptr_t) noexcept { return type.isValid(); }
201
203 [[nodiscard]] friend bool operator!=(const Type& type, std::nullptr_t) noexcept { return !type.isValid(); }
204
206 [[nodiscard]] friend bool operator==(std::nullptr_t, const Type& type) noexcept { return type.isValid(); }
207
209 [[nodiscard]] friend bool operator!=(std::nullptr_t, const Type& type) noexcept { return !type.isValid(); }
210
211 [[nodiscard]] friend bool operator==(const Type& lhs, const Type& rhs) noexcept { return lhs.mTypeInfo == rhs.mTypeInfo; }
212 [[nodiscard]] friend bool operator!=(const Type& lhs, const Type& rhs) noexcept { return lhs.mTypeInfo == rhs.mTypeInfo; }
213
214 [[nodiscard]] friend bool operator<(const Type& lhs, const Type& rhs) noexcept { return lhs.mTypeInfo < rhs.mTypeInfo; }
215 [[nodiscard]] friend bool operator<=(const Type& lhs, const Type& rhs) noexcept { return lhs.mTypeInfo <= rhs.mTypeInfo; }
216 [[nodiscard]] friend bool operator>(const Type& lhs, const Type& rhs) noexcept { return lhs.mTypeInfo > rhs.mTypeInfo; }
217 [[nodiscard]] friend bool operator>=(const Type& lhs, const Type& rhs) noexcept { return lhs.mTypeInfo >= rhs.mTypeInfo; }
218
219 private:
220 friend class Class;
221 friend class Enum;
222 friend class Box;
223
224 [[nodiscard]] void* allocate() const;
225 void deallocate(void* ptr) const;
226 void defaultConstruct(void* where) const;
227 void copyConstruct(const void* source, void* where) const;
228 void moveConstruct(void* source, void* where) const;
229 void moveOrCopy(void* source, void* where) const;
230 void destroy(void* ptr) const noexcept;
231 [[nodiscard]] bool compareEquality(const void* lhs, const void* rhs) const;
232
233 template<typename From, typename To, typename Func> static bool registerConverterInternal(Func&& func);
234 template<typename From, typename To> static bool registerConverterInternal(To (From::*func)() const);
235 template<typename From, typename To> static bool registerConverterInternal(To (From::*func)(bool&) const);
237
238 template<typename From, typename To> static bool registerConverterInternalNonChecked();
240
241 [[nodiscard]] static bool convert(const void* from, Type fromType, void* to, Type toType);
242 [[nodiscard]] static bool convert(const void* from, TypeID fromTypeID, void* to, TypeID toTypeID);
243 };
244
245 template<typename T> [[nodiscard]] constexpr TypeID getTypeID();
246
247 template<> [[nodiscard]] CE_FLATTEN_INLINE inline TypeID getTypeID<void>() { return TypeID{}; }
248 template<typename T> [[nodiscard]] CE_FLATTEN_INLINE inline Type getType() { return Type{getTypeID<T>()}; }
249 template<typename T> [[nodiscard]] CE_FLATTEN_INLINE inline Type getType(T&&) { return Type{getTypeID<T>()}; }
250
251 // ---------------------------------------------------------------------------------------------
252
253 namespace internal {
254
255 template<typename From, typename To> [[nodiscard]] To defaultConvert(const From& value) { return static_cast<To>(value); }
256
258 using converter_t = bool (*)(const ConvertFunctionBase&, const void*, void*);
259
265
266 explicit ConvertFunctionBase(const converter_t converter) : mConverter(converter) {}
267
268 [[nodiscard]] bool invoke(const void* in, void* out) const { return mConverter(*this, in, out); }
269
270 private:
272 };
273
274 template<typename From, typename To, typename F> struct ConvertFunctor : ConvertFunctionBase {
276
277 explicit ConvertFunctor(const F& func) : ConvertFunctionBase{convert}, mFunc(func) {}
278 explicit ConvertFunctor(F&& func) : ConvertFunctionBase{convert}, mFunc(std::move(func)) {}
279 ~ConvertFunctor() { Type::unregisterConverter<From, To>(); }
280
281 [[nodiscard]] static bool convert(const ConvertFunctionBase& self, const void* in, void* out) {
282 try {
283 auto& _this = static_cast<const this_t&>(self);
284 auto from = static_cast<const From*>(in);
285 new(out) To(_this.mFunc(*from));
286 return true;
287 } catch(...) {
288 return false;
289 }
290 }
291
292 private:
293 F const mFunc;
294 };
295
296 template<typename From, typename To, typename F> struct ConvertFunctorOk : ConvertFunctionBase {
298
299 explicit ConvertFunctorOk(const F& func) : ConvertFunctionBase{convert}, mFunc(func) {}
301 ~ConvertFunctorOk() { Type::unregisterConverter<From, To>(); }
302
303 [[nodiscard]] static bool convert(const ConvertFunctionBase& self, const void* in, void* out) {
304 auto& _this = static_cast<const this_t&>(self);
305 auto from = static_cast<const From*>(in);
306 auto result = false;
307 new(out) To(_this.mFunc(*from, result));
308 return result;
309 }
310
311 private:
312 F const mFunc;
313 };
314
315 template<typename From, typename To> struct ConvertMethod : ConvertFunctionBase {
317 using func_t = To (From::*)() const;
318
319 explicit ConvertMethod(const func_t func) : ConvertFunctionBase{convert}, mFunc(func) {}
320
321 ~ConvertMethod() { Type::unregisterConverter<From, To>(); }
322
323 [[nodiscard]] static bool convert(const ConvertFunctionBase& self, const void* in, void* out) {
324 try {
325 auto& _this = static_cast<const this_t&>(self);
326 auto from = static_cast<const From*>(in);
327 new(out) To(from->*_this.mFunc());
328 return true;
329 } catch(...) {
330 return false;
331 }
332 }
333
334 private:
336 };
337
338 template<typename From, typename To> struct ConvertMethodOk : ConvertFunctionBase {
340 using func_t = To (From::*)(bool&) const;
341
342 explicit ConvertMethodOk(const func_t func) : ConvertFunctionBase{convert}, mFunc(func) {}
343
344 ~ConvertMethodOk() { Type::unregisterConverter<From, To>(); }
345
346 [[nodiscard]] static bool convert(const ConvertFunctionBase& self, const void* in, void* out) {
347 auto& _this = static_cast<const this_t&>(self);
348 auto from = static_cast<const From*>(in);
349 auto result = false;
350 new(out) To(from->*_this.mFunc(result));
351 return result;
352 }
353
354 private:
356 };
357
358 } // namespace internal
359
360 template<typename From, typename To> inline bool Type::hasConverter() noexcept { return hasConverter(CeresEngine::getTypeID<From>(), CeresEngine::getTypeID<To>()); }
361
362 // Functor converter
363
364 template<typename From, typename To, typename Func> inline bool Type::registerConverterInternal(Func&& func) {
365 using Fu = full_decay<Func>;
366
367 if constexpr(std::is_invocable_r_v<To, Func, From, bool&>) {
368 static internal::ConvertFunctorOk<From, To, Fu> converter{std::forward<Func>(func)};
370 } else {
371 static internal::ConvertFunctor<From, To, Fu> converter{std::forward<Func>(func)};
373 }
374 }
375
376 template<typename From, typename To, typename Func> inline bool Type::registerConverter(Func&& func) {
377 using F = full_decay<From>;
378 using T = full_decay<To>;
379 return registerConverterInternal<F, T>(std::forward<Func>(func));
380 }
381
382 template<typename From, typename To> inline bool Type::registerConverter(To (*func)(From)) {
383 using Func = To (*)(From);
384 return registerConverter<From, To, Func>(std::move(func));
385 }
386
387 template<typename From, typename To> inline bool Type::registerConverter() { return registerConverter<From, To>(internal::defaultConvert<From, To>); }
388
389 template<typename From, typename To> inline bool Type::registerConverterInternalNonChecked() {
390 static internal::ConvertFunctor<From, To, decltype(&internal::defaultConvert<From, To>)> converter{internal::defaultConvert<From, To>};
392 }
393
394 // Method converter
395
396 template<typename From, typename To> inline bool Type::registerConverterInternal(To (From::*func)() const) {
397 static internal::ConvertMethod<From, To> converter{func};
399 }
400
401 template<typename From, typename To> inline bool Type::registerConverter(To (From::*func)() const) {
402 using F = full_decay<From>;
403 using T = full_decay<To>;
405 }
406
407 // Method extended converter
408
409 template<typename From, typename To> inline bool Type::registerConverterInternal(To (From::*func)(bool&) const) {
410 static internal::ConvertMethodOk<From, To> converter{func};
412 }
413
414 template<typename From, typename To> inline bool Type::registerConverter(To (From::*func)(bool&) const) {
415 using F = full_decay<From>;
416 using T = full_decay<To>;
418 }
419
421
423 std::ostream& operator<<(std::ostream& stream, Type type);
424
425 template<typename T> [[nodiscard]] CE_FLATTEN_INLINE constexpr TypeID getTypeID() { return TypeID(reinterpret_cast<UInt64>(&GetTypeInfo<T>::get())); }
426
427 // ---------------------------------------------------------------------------------------------
428
429 template<typename T> [[nodiscard]] bool Type::is() const { return mTypeInfo != nullptr && mTypeInfo->is<T>(); }
430 template<typename T> [[nodiscard]] const T* Type::as() const {
431 if(mTypeInfo == nullptr) {
432 return nullptr;
433 }
434 return mTypeInfo->as<T>();
435 }
436
437 template<typename T> [[nodiscard]] bool Type::compatible() const noexcept { return compatible(*this, getType<T>()); }
438
439 // ---------------------------------------------------------------------------------------------
440
446
450
451 // ---------------------------------------------------------------------------------------------
452
453 #define CE_META_CONCAT_IMPL(A, B) A##B
454 #define CE_META_CONCAT(A, B) CE_META_CONCAT_IMPL(A, B)
455
456#define CE_META_TYPE_AUTO_REGISTRATION_NAME(T) CE_META_CONCAT(gTypeAutoRegistrator, __COUNTER__)
457#define CE_META_TYPE_AUTO_REGISTRATION(T) static const ::CeresEngine::TypeAutoRegistration<T> CE_META_TYPE_AUTO_REGISTRATION_NAME(T)
458
459} //namespace CeresEngine
460
462template<> struct std::hash<CeresEngine::Type> {
463 using Type = CeresEngine::Type;
464 [[nodiscard]] size_t operator()(const Type& value) const { return CeresEngine::hash(value.getTypeID().raw); }
465};
A value type that can hold any alongside it's type information.
Definition Box.hpp:40
Definition Class.hpp:46
Represents a reflected enum from C++.
Definition Enum.hpp:26
Represents a reflected C++ type. Can be used to get metadata from a C++ type.
Definition Type.hpp:32
bool isVoidPtr() const noexcept
Returns true if the type is a void pointer, false otherwise.
bool isValid() const noexcept
Determines if the Type object points to a valid type or not.
Definition Type.hpp:194
static Type fromID(TypeID id) noexcept
Finds a type by it's id.
bool isClassPtr() const noexcept
Returns true if the type is a class pointer, false otherwise.
static bool registerConverter()
Definition Type.hpp:387
friend bool operator!=(const Type &type, std::nullptr_t) noexcept
Determines if the Type object points to a valid type or not.
Definition Type.hpp:203
StringView getName() const noexcept
Definition Type.hpp:67
friend bool operator>(const Type &lhs, const Type &rhs) noexcept
Definition Type.hpp:216
static bool convert(const void *from, TypeID fromTypeID, void *to, TypeID toTypeID)
bool isPointer() const noexcept
Returns true if the type is a pointer, false otherwise.
static bool registerConverter(TypeID fromTypeID, TypeID toTypeID, const internal::ConvertFunctionBase &converter)
uint16_t getPointerArity() const noexcept
Returns the pointer arity of the type. Returns 0 if the type is not a pointer.
void deallocate(void *ptr) const
void * allocate() const
TypeID getTypeID() const noexcept
Gets the type ID.
TypeID getDecayTypeID() const noexcept
Gets the decayed type.
bool compatible() const noexcept
Determines if the fromType is compatible with the toType.
Definition Type.hpp:437
static void unregisterConverter()
Definition Type.hpp:420
const TypeInfo * mTypeInfo
The TypeInfo structure that describes the reflected type.
Definition Type.hpp:35
static bool hasConverter() noexcept
Determines if there is a converter available to convert a value from From to To.
Definition Type.hpp:360
void moveOrCopy(void *source, void *where) const
Type getDecayType() const noexcept
Gets the decayed type.
Type(TypeID typeID) noexcept
Finds a type by it's id.
bool isFunctionPtr() const noexcept
Returns true if the type is a function pointer, false otherwise.
TypeIdentityHash getIdentityHash() const noexcept
Gets the type identity hash.
static bool registerConverterInternal(Func &&func)
Definition Type.hpp:364
TypeID getUnderlyingTypeID() const noexcept
If an enum, gets the underlying type of the enum.
StringView getTypeName() const noexcept
bool compareEquality(const void *lhs, const void *rhs) const
friend bool operator<(const Type &lhs, const Type &rhs) noexcept
Definition Type.hpp:214
friend bool operator!=(const Type &lhs, const Type &rhs) noexcept
Definition Type.hpp:212
friend bool operator!=(std::nullptr_t, const Type &type) noexcept
Determines if the Type object points to a valid type or not.
Definition Type.hpp:209
bool isRvalueReference() const noexcept
Returns true if the type is an rvalue reference, false otherwise.
const Enum * getMetaEnum() const noexcept
Gets the MetaEnum instance associated with the type.
bool compatible(const Type &other) const noexcept
Determines if the fromType is compatible with the toType.
Definition Type.hpp:160
bool isClass() const noexcept
Returns true if the type is a class, false otherwise.
void copyConstruct(const void *source, void *where) const
void destruct(void *instance) const
Destroys an instance of the type. Calls the C++ destructor.
void defaultConstruct(void *where) const
bool isDecayed() const noexcept
Determines if the type is decayed, that is, this->getDecayedType() == this.
Definition Type.hpp:84
void moveConstruct(void *source, void *where) const
static Type fromName(StringView name) noexcept
Finds a type by it's name.
bool is() const
Definition Type.hpp:429
friend bool operator==(const Type &type, std::nullptr_t) noexcept
Determines if the Type object points to a valid type or not.
Definition Type.hpp:200
static bool registerConverterInternalNonChecked()
Definition Type.hpp:389
bool isLvalueReference() const noexcept
Returns true if the type is an lvalue reference, false otherwise.
bool isReference() const noexcept
Returns true if the type is a reference (lvalue or rvalue), false otherwise.
static bool registerConverterInternalNonChecked(TypeID fromTypeID, TypeID toTypeID, const internal::ConvertFunctionBase &converter)
friend bool operator==(std::nullptr_t, const Type &type) noexcept
Determines if the Type object points to a valid type or not.
Definition Type.hpp:206
std::size_t getTypeSize() const noexcept
bool isArray() const noexcept
Returns true if the type is an array, false otherwise.
bool isConst() const noexcept
Returns true if the type is const, false otherwise.
friend bool operator==(const Type &lhs, const Type &rhs) noexcept
Definition Type.hpp:211
Type(StringView name) noexcept
Finds a type by it's name.
std::align_val_t getTypeAlignment() const noexcept
void destroy(void *ptr) const noexcept
const Class * getClass() const noexcept
Gets the Class instance associated with the type.
Type() noexcept=default
Type getUnderlyingType() const noexcept
If an enum, gets the underlying type of the enum.
Box construct() const
Constructs a new value from the type, if default constructible.
friend bool operator>=(const Type &lhs, const Type &rhs) noexcept
Definition Type.hpp:217
const T * as() const
Definition Type.hpp:430
friend bool operator<=(const Type &lhs, const Type &rhs) noexcept
Definition Type.hpp:215
static bool convert(const void *from, Type fromType, void *to, Type toType)
Definition TypeInfo.hpp:36
bool is() const noexcept
Definition TypeInfo.hpp:60
const T * as() const noexcept
Definition TypeInfo.hpp:61
To defaultConvert(const From &value)
Definition Type.hpp:255
Definition Application.hpp:19
std::uint64_t UInt64
Definition DataTypes.hpp:26
UInt64 TypeIdentityHash
A type that represents a Type hash value.
Definition Type.hpp:29
TypedID< internal::TypeTag, UInt64 > TypeID
Definition Forward.hpp:45
remove_all_cv< std::decay_t< T > > full_decay
Definition TypeTraits.hpp:97
decltype(auto) get(BezierPath::Element &element) noexcept
Decomposes a bezier path element.
Definition BezierPath.hpp:723
constexpr Byte operator<<(const Byte arg, const _IntType shift) noexcept
Definition DataTypes.hpp:44
CE_FLATTEN_INLINE Type getType()
Definition Type.hpp:248
auto move(Vector3 position)
Moves a entity to the given position.
Definition Helpers.hpp:22
CE_FLATTEN_INLINE TypeID getTypeID< void >()
Definition Type.hpp:247
constexpr TypeID getTypeID()
Definition Type.hpp:425
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
Definition Span.hpp:668
Definition Forward.hpp:34
TypeAutoRegistrationBase(const TypeInfo &type)
const TypeInfo & type
Definition Type.hpp:442
Definition Type.hpp:447
TypeAutoRegistration()
Definition Type.hpp:448
bool invoke(const void *in, void *out) const
Definition Type.hpp:268
ConvertFunctionBase(ConvertFunctionBase &&)=delete
converter_t mConverter
Definition Type.hpp:271
ConvertFunctionBase(const converter_t converter)
Definition Type.hpp:266
ConvertFunctionBase & operator=(const ConvertFunctionBase &)=delete
ConvertFunctionBase(const ConvertFunctionBase &)=delete
bool(*)(const ConvertFunctionBase &, const void *, void *) converter_t
Definition Type.hpp:258
ConvertFunctionBase & operator=(ConvertFunctionBase &&)=delete
~ConvertFunctor()
Definition Type.hpp:279
F const mFunc
Definition Type.hpp:293
static bool convert(const ConvertFunctionBase &self, const void *in, void *out)
Definition Type.hpp:281
ConvertFunctor(F &&func)
Definition Type.hpp:278
ConvertFunctor(const F &func)
Definition Type.hpp:277
~ConvertFunctorOk()
Definition Type.hpp:301
static bool convert(const ConvertFunctionBase &self, const void *in, void *out)
Definition Type.hpp:303
F const mFunc
Definition Type.hpp:312
ConvertFunctorOk(const F &func)
Definition Type.hpp:299
ConvertFunctorOk(F &&func)
Definition Type.hpp:300
static bool convert(const ConvertFunctionBase &self, const void *in, void *out)
Definition Type.hpp:323
To(From::*)() const func_t
Definition Type.hpp:317
~ConvertMethod()
Definition Type.hpp:321
ConvertMethod(const func_t func)
Definition Type.hpp:319
func_t const mFunc
Definition Type.hpp:335
~ConvertMethodOk()
Definition Type.hpp:344
ConvertMethodOk(const func_t func)
Definition Type.hpp:342
static bool convert(const ConvertFunctionBase &self, const void *in, void *out)
Definition Type.hpp:346
func_t const mFunc
Definition Type.hpp:355
To(From::*)(bool &) const func_t
Definition Type.hpp:340