MCRO
C++23 utilities for Unreal Engine.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
Types.h
Go to the documentation of this file.
1/** @noop License Comment
2 * @file
3 * @copyright
4 * This Source Code is subject to the terms of the Mozilla Public License, v2.0.
5 * If a copy of the MPL was not distributed with this file You can obtain one at
6 * https://mozilla.org/MPL/2.0/
7 *
8 * @author David Mórász
9 * @date 2025
10 */
11
12#pragma once
13
14#include <string>
15
16#include "CoreMinimal.h"
17#include "Mcro/TypeName.h"
18#include "Mcro/Templates.h"
19
20/** @brief C++ native static reflection utilities, not to be confused with reflection of UObjects */
21namespace Mcro::Types
22{
23 using namespace Mcro::TypeName;
24 using namespace Mcro::Templates;
25
26 class IHaveType;
27
28 template <typename T>
29 concept CHasTypeName = CDerivedFrom<T, IHaveType>;
30
31 /**
32 * @brief A barebones base class for types which may store their type-name as a string
33 *
34 * @todo
35 * C++ 26 has promising proposal for static value-based reflection, which can gather metadata from classes
36 * or even emit them. The best summary I found so far is a stack-overflow answer https://stackoverflow.com/a/77477029
37 * Once that's available we can gather base classes in compile time, and do dynamic casting of objects without
38 * the need for intrusive extra syntax, or extra work at construction.
39 * Currently GCC's `__bases` would be perfect for the job, but other popular compilers don't have similar intrinsics.
40 *
41 * @warning
42 * Do not use exact type comparison with serialized data or network communication, as the actual value of the type
43 * is different between compilers. Only use this for runtime data. For such scenarios just use Unreal's own UObjects.
44 */
45 class IHaveType : public TSharedFromThis<IHaveType>
46 {
47 public:
48 virtual ~IHaveType() = default;
49
50 protected:
51 FName TypeName;
53
54 /** @brief This function needs to be called on top level derived type for runtime reflection to work */
55 template <typename Self>
56 void SetType(this Self&& self)
57 {
58 self.TypeName = TTypeFName<Self>();
59 self.TypeInfo = TTypeOf<Self>;
60 }
61
62 public:
63 template <typename Self>
64 using SelfRef = TSharedRef<std::decay_t<Self>>;
65
66 /** @brief Fluent API for setting tpye for deferred initialization (for example in factory functions) */
67 template <typename Self>
68 SelfRef<Self> WithType(this Self&& self)
69 {
70 self.SetType();
71 return SharedThis(&self);
72 }
73
74 FORCEINLINE FType const& GetType() const { return TypeInfo; }
75 FORCEINLINE FName const& GetTypeFName() const { return TypeName; }
76 FORCEINLINE FString GetTypeString() const { return TypeName.ToString(); }
77
78 /**
79 * @brief Very simple dynamic casting of this object to a derived top-level type.
80 *
81 * @tparam Derived
82 * Only return the desired type when the current object is exactly that type, and doesn't have deeper
83 * inheritance. Proper dynamic casting regarding the entire inheritance tree still without RTTI will come once
84 * proposed C++26 value-typed reflection becomes wide-spread available among popular compilers.
85 *
86 * @return Object cast to desired type when that's possible (see `Derived`) or nullptr;
87 */
88 template <typename Derived, typename Self>
89 TSharedPtr<Derived> AsExactly(this Self&& self)
90 {
91 if constexpr (CDerivedFrom<Derived, Self>)
92 if (self.TypeInfo == TTypeOf<Derived>)
93 return StaticCastSharedPtr<Derived>(
94 SharedThis(AsMutablePtr(&self)).ToSharedPtr()
95 );
96 return {};
97 }
98 };
99}
Convert types to string.
A barebones base class for types which may store their type-name as a string.
Definition Types.h:46
TSharedPtr< Derived > AsExactly(this Self &&self)
Very simple dynamic casting of this object to a derived top-level type.
Definition Types.h:89
virtual ~IHaveType()=default
FORCEINLINE FString GetTypeString() const
Definition Types.h:76
FORCEINLINE FName const & GetTypeFName() const
Definition Types.h:75
FORCEINLINE FType const & GetType() const
Definition Types.h:74
void SetType(this Self &&self)
This function needs to be called on top level derived type for runtime reflection to work.
Definition Types.h:56
SelfRef< Self > WithType(this Self &&self)
Fluent API for setting tpye for deferred initialization (for example in factory functions)
Definition Types.h:68
TSharedRef< std::decay_t< Self > > SelfRef
Definition Types.h:64
This namespace provide some introspection into template instantiations.
Definition Templates.h:27
auto AsMutablePtr(T *input)
Tired of typing const_cast<FMyLongUnwieldyTypeName*>(...)? use this instead.
Definition Templates.h:177
FName TTypeFName()
Same as TTypeName converted to FName. This is not cached and a new FName is created every time this i...
Definition TypeName.h:213
constexpr FType TTypeOf
Definition TypeName.h:144
C++ native static reflection utilities, not to be confused with reflection of UObjects.
Definition Types.h:22
Group together type info for identification. Can have an invalid state when no type is specified.
Definition TypeName.h:110