UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
PointerVariants.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "Misc/TVariant.h"
10#include "UnrealTypeTraits.h"
11#include "UnrealTemplate.h"
12
13#include <type_traits>
14
15/*
16* `TWeakPtrVariant` and `TStrongPtrVariant` are particularly useful for "interfaces" in areas where
17* UObjects and non-UObjects exist to hold onto a "smart" pointer to the Interface, rather than needing to keep track of the implementing class to check validity and manually cast
18*/
19
20/* `TWeakPtrVariant` will be either a `TWeakObjectPtr` or `TWeakPtr` */
21template<typename BaseType>
22struct TWeakPtrVariant;
23
24/* `TStrongPtrVariant` will be either a `TStrongObjectPtr` or `TSharedPtr` */
25template<typename BaseType>
27
28namespace UE::Core::Private
29{
30 template<typename BaseType, bool bIsStrong>
31 struct TPtrVariantBase;
32
33 template <typename LhsType, bool bLhsStrength, typename RhsType, bool bRhsStrength
34 UE_REQUIRES(UE_REQUIRES_EXPR((LhsType*)nullptr == (RhsType*)nullptr))
35 >
37
38 template<typename LhsType, typename RhsType, bool bRhsStrength
39 UE_REQUIRES(UE_REQUIRES_EXPR((LhsType*)nullptr == (RhsType*)nullptr))
40 >
42
43 template<typename LhsType, bool bLhsStrength, typename RhsType
44 UE_REQUIRES(UE_REQUIRES_EXPR((LhsType*)nullptr == (RhsType*)nullptr))
45 >
47
48 template<typename BaseType, bool bIsStrong>
50 {
51 friend struct TWeakPtrVariant<BaseType>;
52 friend struct TStrongPtrVariant<BaseType>;
53
54 using SharedType = std::conditional_t<bIsStrong, TSharedPtr<BaseType>, TWeakPtr<BaseType>>;
55
57 {
58 using ObjectPtrType = std::conditional_t<bIsStrong, TStrongObjectPtr<const UObject>, TWeakObjectPtr<const UObject>>;
59
65
67 BaseType* CastedPtr = nullptr;
68 };
69
70 public:
71 constexpr TPtrVariantBase() = default;
73 {
74 }
75
76 template <
77 typename DerivedType
78 UE_REQUIRES(std::is_convertible_v<DerivedType*, BaseType*> && (std::is_base_of_v<UObject, DerivedType> || IsDerivedFromSharedFromThis<DerivedType>()))
79 >
80 constexpr TPtrVariantBase(DerivedType* InDerived)
81 {
82 // TODO: Look for a way to move this "smart pointer selection" logic outside of the constructor; then we can remove "TVariant" as a dependency
83 // The problem is that "DerivedType" is defined in the constructor; We don't want TWeakPtrVariant or TStrongPtrVariant to have "DerivedType" as part of their template args
84 if constexpr (std::is_base_of_v<UObject, DerivedType>)
85 {
87 }
88 else
89 {
90 if constexpr (bIsStrong)
91 {
93 }
94 else
95 {
97 }
98 }
99 }
100
102 {
103 Reset();
104 return *this;
105 }
106
107 bool IsValid() const
108 {
109 return ::Visit([](auto& StoredValue)
110 {
111 using StoredValueType = std::decay_t<decltype(StoredValue)>;
112 if constexpr (std::is_same_v<StoredValueType, SharedType>)
113 {
114 return StoredValue.IsValid();
115 }
116 else
117 {
118 return StoredValue.ObjectPtr.IsValid();
119 }
120 }, PtrVariant);
121 }
122
123 void Reset()
124 {
125 ::Visit([](auto& StoredValue)
126 {
127 using StoredValueType = std::decay_t<decltype(StoredValue)>;
128 if constexpr (std::is_same_v<StoredValueType, SharedType>)
129 {
130 StoredValue.Reset();
131 }
132 else
133 {
134 StoredValue.ObjectPtr.Reset();
135 }
136 }, PtrVariant);
137 }
138
139 private:
140 template <typename LhsType, bool bLhsStrength, typename RhsType, bool bRhsStrength
141 UE_REQUIRES_FRIEND(UE_REQUIRES_EXPR((LhsType*)nullptr == (RhsType*)nullptr))
142 >
144
145 template<typename LhsType, typename RhsType, bool bRhsStrength
146 UE_REQUIRES_FRIEND(UE_REQUIRES_EXPR((LhsType*)nullptr == (RhsType*)nullptr))
147 >
149
150 template<typename LhsType, bool bLhsStrength, typename RhsType
151 UE_REQUIRES_FRIEND(UE_REQUIRES_EXPR((LhsType*)nullptr == (RhsType*)nullptr))
152 >
154
155 private:
156 const BaseType* GetRawPtrValue_Internal() const
157 {
158 return ::Visit([this](auto& StoredValue)
159 {
160 using StoredValueType = std::decay_t<decltype(StoredValue)>;
161 if constexpr (std::is_same_v<StoredValueType, SharedType>)
162 {
163 if constexpr (bIsStrong)
164 {
165 return IsValid() ? StoredValue.Get() : (const BaseType*)nullptr;
166 }
167 else
168 {
169 return IsValid() ? StoredValue.Pin().Get() : (const BaseType*)nullptr;
170 }
171 }
172 else
173 {
174 return IsValid() ? StoredValue.CastedPtr : (const BaseType*)nullptr;
175 }
176 }, PtrVariant);
177 }
178
179 private:
181 };
182
183 template <typename LhsType, bool bLhsStrength, typename RhsType, bool bRhsStrength
185 >
187 {
188 return Lhs.GetRawPtrValue_Internal() == Rhs.GetRawPtrValue_Internal();
189 }
190
191 template <typename LhsType, bool bLhsStrength, typename RhsType, bool bRhsStrength>
193 {
194 return !(Lhs == Rhs);
195 }
196
197 template<typename LhsType, typename RhsType, bool bRhsStrength
199 >
201 {
202 return Lhs == Rhs.GetRawPtrValue_Internal();
203 }
204
205 template<typename LhsType, typename RhsType, bool bRhsStrength>
207 {
208 return !(Lhs == Rhs);
209 }
210
211 template<typename LhsType, bool bLhsStrength, typename RhsType
213 >
215 {
216 return Lhs.GetRawPtrValue_Internal() == Rhs;
217 }
218
219 template<typename LhsType, bool bLhsStrength, typename RhsType>
221 {
222 return !(Lhs == Rhs);
223 }
224} // namespace UE::Core::Private
225
226template<typename BaseType>
228{
230 using Super::Super;
231
232 BaseType* Get() const
233 {
234 return ::Visit([](const auto& StoredValue)
235 {
236 using StoredValueType = std::decay_t<decltype(StoredValue)>;
238 {
239 return StoredValue.Get();
240 }
241 else
242 {
243 return StoredValue.CastedPtr;
244 }
245 }, Super::PtrVariant);
246 }
247
249 {
250 if (Super::IsValid())
251 {
252 return ::Visit([](auto& StoredValue)
253 {
255
256 using StoredValueType = std::decay_t<decltype(StoredValue)>;
258 {
260 }
261 else
262 {
264 }
265
266 return WeakPtrVariant;
267 }, Super::PtrVariant);
268 }
269 else
270 {
272 }
273 }
274};
275
276template<typename BaseType>
278{
280 using Super::Super;
281
283 {
284 if (Super::IsValid())
285 {
286 return ::Visit([](auto& StoredValue)
287 {
289
290 using StoredValueType = std::decay_t<decltype(StoredValue)>;
291 if constexpr (TIsTWeakPtr_V<StoredValueType>)
292 {
294 }
295 else
296 {
298 }
299
300 return StrongPtrVariant;
301 }, Super::PtrVariant);
302 }
303 else
304 {
306 }
307 }
308};
FPlatformTypes::TYPE_OF_NULLPTR TYPE_OF_NULLPTR
The type of the C++ nullptr keyword.
Definition Platform.h:1157
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define UE_REQUIRES_DEFINITION(...)
Definition Requires.h:88
#define UE_REQUIRES_FRIEND(...)
Definition Requires.h:87
#define UE_REQUIRES(...)
Definition Requires.h:86
#define UE_REQUIRES_EXPR(...)
Definition Requires.h:89
decltype(auto) Visit(Func &&Callable, Variants &&... Args)
Definition TVariant.h:271
Definition TVariant.h:48
Definition SharedPointer.h:1295
Definition Object.h:95
implementation
Definition PlayInEditorLoadingScope.h:8
bool operator==(const TPtrVariantBase< LhsType, bLhsStrength > &Lhs, const TPtrVariantBase< RhsType, bRhsStrength > &Rhs)
Definition PointerVariants.h:186
bool operator!=(const TPtrVariantBase< LhsType, bLhsStrength > &Lhs, const TPtrVariantBase< RhsType, bRhsStrength > &Rhs)
Definition PointerVariants.h:192
Definition PointerVariants.h:228
TWeakPtrVariant< BaseType > ToWeakVariant() const
Definition PointerVariants.h:248
BaseType * Get() const
Definition PointerVariants.h:232
Definition WeakObjectPtrTemplates.h:25
Definition PointerVariants.h:278
TStrongPtrVariant< BaseType > Pin() const
Definition PointerVariants.h:282
std::conditional_t< bIsStrong, TStrongObjectPtr< const UObject >, TWeakObjectPtr< const UObject > > ObjectPtrType
Definition PointerVariants.h:58
FObjectPtrWrapper(const UObject *InObjectPtr, BaseType *const InCastedPtr)
Definition PointerVariants.h:60
BaseType * CastedPtr
Definition PointerVariants.h:67
ObjectPtrType ObjectPtr
Definition PointerVariants.h:66
Definition PointerVariants.h:50
friend bool operator==(const TPtrVariantBase< LhsType, bLhsStrength > &Lhs, const TPtrVariantBase< RhsType, bRhsStrength > &Rhs)
Definition PointerVariants.h:186
friend struct TWeakPtrVariant< BaseType >
Definition PointerVariants.h:51
constexpr TPtrVariantBase()=default
bool IsValid() const
Definition PointerVariants.h:107
friend bool operator==(const TPtrVariantBase< LhsType, bLhsStrength > &Lhs, RhsType *Rhs)
Definition PointerVariants.h:214
friend bool operator==(LhsType *Lhs, const TPtrVariantBase< RhsType, bRhsStrength > &Rhs)
Definition PointerVariants.h:200
TPtrVariantBase & operator=(TYPE_OF_NULLPTR)
Definition PointerVariants.h:101
std::conditional_t< bIsStrong, TSharedPtr< BaseType >, TWeakPtr< BaseType > > SharedType
Definition PointerVariants.h:54
constexpr TPtrVariantBase(DerivedType *InDerived)
Definition PointerVariants.h:80
constexpr TPtrVariantBase(TYPE_OF_NULLPTR)
Definition PointerVariants.h:72
void Reset()
Definition PointerVariants.h:123
friend struct TStrongPtrVariant< BaseType >
Definition PointerVariants.h:52