UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Union.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
6#include "HAL/PlatformCrt.h"
8#include "Logging/LogMacros.h"
15
16
18
19
21template<uint32>
23{
25};
26
27
28class FNull
29{
30public:
31
33 {
34 return 0;
35 }
36
37 bool operator==(const FNull&) const
38 {
39 return true;
40 }
41
42 bool operator!=(const FNull&) const
43 {
44 return false;
45 }
46
48 {
49 // nothing
50 return Ar;
51 }
52};
53
54
62template<typename TypeA,typename TypeB = FNull,typename TypeC = FNull,typename TypeD = FNull,typename TypeE = FNull,typename TypeF = FNull>
63class TUnion
64{
65public:
66
69 { }
70
76
82
88
94
100
106
109 {
110 *this = Other;
111 }
112
115 {
116 // Destruct any subtype value the union may have.
117 Reset();
118 }
119
121 template<typename Subtype>
122 bool HasSubtype() const
123 {
124 // Determine the subtype's index and reference.
126 const Subtype* SubtypeValuePointer;
128
129 return CurrentSubtypeIndex == SubtypeIndex;
130 }
131
133 template<typename Subtype>
135 {
136 // Determine the subtype's index and reference.
138 Subtype* SubtypeValuePointer;
140
141 // Only reset the value if it is of the specified subtype.
142 if(CurrentSubtypeIndex == SubtypeIndex)
143 {
144 CurrentSubtypeIndex = -1;
145
146 // Destruct the subtype.
147 SubtypeValuePointer->~Subtype();
148 }
149 }
150
152 template<typename Subtype>
153 const Subtype& GetSubtype() const
154 {
155 // Determine the subtype's index and reference.
157 const Subtype* SubtypeValuePointer;
159
160 // Validate that the union has a value of the requested subtype.
161 check(CurrentSubtypeIndex == SubtypeIndex);
162
163 return *SubtypeValuePointer;
164 }
165
167 template<typename Subtype>
168 Subtype& GetSubtype()
169 {
170 // Determine the subtype's index and reference.
172 Subtype* SubtypeValuePointer;
174
175 // Validate that the union has a value of the requested subtype.
176 check(CurrentSubtypeIndex == SubtypeIndex);
177
178 return *SubtypeValuePointer;
179 }
180
182 template<typename Subtype>
183 Subtype* SetSubtype()
184 {
186 Subtype* SubtypeValuePointer;
188
189 Reset();
190
191 ::new((void*)SubtypeValuePointer) Subtype();
192
193 CurrentSubtypeIndex = SubtypeIndex;
194 return SubtypeValuePointer;
195 }
196
198 template<typename Subtype>
199 Subtype* SetSubtype(typename TCallTraits<Subtype>::ParamType NewValue)
200 {
202 Subtype* SubtypeValuePointer;
204
205 Reset();
206
207 ::new((void*)SubtypeValuePointer) Subtype(NewValue);
208
209 CurrentSubtypeIndex = SubtypeIndex;
210 return SubtypeValuePointer;
211 }
212
215 {
216 return CurrentSubtypeIndex;
217 }
218
220 void Reset()
221 {
222 switch(CurrentSubtypeIndex)
223 {
224 case 0: ResetSubtype<TypeA>(); break;
225 case 1: ResetSubtype<TypeB>(); break;
226 case 2: ResetSubtype<TypeC>(); break;
227 case 3: ResetSubtype<TypeD>(); break;
228 case 4: ResetSubtype<TypeE>(); break;
229 case 5: ResetSubtype<TypeF>(); break;
230 };
231 }
232
235 {
236 uint32 Result = GetTypeHash(Union.CurrentSubtypeIndex);
237
238 switch(Union.CurrentSubtypeIndex)
239 {
240 case 0: Result ^= GetTypeHash(Union.GetSubtype<TypeA>()); break;
241 case 1: Result ^= GetTypeHash(Union.GetSubtype<TypeB>()); break;
242 case 2: Result ^= GetTypeHash(Union.GetSubtype<TypeC>()); break;
243 case 3: Result ^= GetTypeHash(Union.GetSubtype<TypeD>()); break;
244 case 4: Result ^= GetTypeHash(Union.GetSubtype<TypeE>()); break;
245 case 5: Result ^= GetTypeHash(Union.GetSubtype<TypeF>()); break;
246 default: FatalErrorUndefinedSubtype(); break;
247 };
248
249 return Result;
250 }
251
253 {
254 // Copy the value of the appropriate subtype from the other union
255 switch (Other.CurrentSubtypeIndex)
256 {
257 case (uint8)-1: break;
258 case 0: SetSubtype<TypeA>(Other.GetSubtype<TypeA>()); break;
259 case 1: SetSubtype<TypeB>(Other.GetSubtype<TypeB>()); break;
260 case 2: SetSubtype<TypeC>(Other.GetSubtype<TypeC>()); break;
261 case 3: SetSubtype<TypeD>(Other.GetSubtype<TypeD>()); break;
262 case 4: SetSubtype<TypeE>(Other.GetSubtype<TypeE>()); break;
263 case 5: SetSubtype<TypeF>(Other.GetSubtype<TypeF>()); break;
264 default: FatalErrorUndefinedSubtype(); break;
265 };
266
267 return *this;
268 }
269
271 bool operator==(const TUnion& Other) const
272 {
273 if(CurrentSubtypeIndex == Other.CurrentSubtypeIndex)
274 {
275 switch(CurrentSubtypeIndex)
276 {
277 case 0: return GetSubtype<TypeA>() == Other.GetSubtype<TypeA>(); break;
278 case 1: return GetSubtype<TypeB>() == Other.GetSubtype<TypeB>(); break;
279 case 2: return GetSubtype<TypeC>() == Other.GetSubtype<TypeC>(); break;
280 case 3: return GetSubtype<TypeD>() == Other.GetSubtype<TypeD>(); break;
281 case 4: return GetSubtype<TypeE>() == Other.GetSubtype<TypeE>(); break;
282 case 5: return GetSubtype<TypeF>() == Other.GetSubtype<TypeF>(); break;
283 default: FatalErrorUndefinedSubtype(); break;
284 };
285 }
286
287 return false;
288 }
289
291 {
292 if(Ar.IsLoading())
293 {
294 Reset();
295
296 Ar << CurrentSubtypeIndex;
297
298 switch(CurrentSubtypeIndex)
299 {
300 case 0: Ar << InitSubtype<TypeA>(); break;
301 case 1: Ar << InitSubtype<TypeB>(); break;
302 case 2: Ar << InitSubtype<TypeC>(); break;
303 case 3: Ar << InitSubtype<TypeD>(); break;
304 case 4: Ar << InitSubtype<TypeE>(); break;
305 case 5: Ar << InitSubtype<TypeF>(); break;
306 default: FatalErrorUndefinedSubtype(); break;
307 };
308 }
309 else
310 {
311 Ar << CurrentSubtypeIndex;
312
313 switch(CurrentSubtypeIndex)
314 {
315 case 0: Ar << GetSubtype<TypeA>(); break;
316 case 1: Ar << GetSubtype<TypeB>(); break;
317 case 2: Ar << GetSubtype<TypeC>(); break;
318 case 3: Ar << GetSubtype<TypeD>(); break;
319 case 4: Ar << GetSubtype<TypeE>(); break;
320 case 5: Ar << GetSubtype<TypeF>(); break;
321 default: FatalErrorUndefinedSubtype(); break;
322 };
323 }
324 }
325
326private:
327
329 union
330 {
337 } Values;
338
340 uint8 CurrentSubtypeIndex = (uint8)-1;
341
343 template<typename Subtype>
344 Subtype& InitSubtype()
345 {
346 Subtype* NewSubtype = &GetSubtype<Subtype>();
347 return *::new((void*)NewSubtype) Subtype;
348 }
349
351 template<typename Subtype,typename PointerType>
352 static void GetSubtypeIndexAndReference(
353 const TUnion& Union,
354 uint8& OutIndex,
355 PointerType& OutValuePointer
356 )
357 {
358 if constexpr (std::is_same_v<TypeA,Subtype>)
359 {
360 OutIndex = 0;
361 OutValuePointer = (PointerType)&Union.Values.A;
362 }
363 else if constexpr (std::is_same_v<TypeB,Subtype>)
364 {
365 OutIndex = 1;
366 OutValuePointer = (PointerType)&Union.Values.B;
367 }
368 else if constexpr (std::is_same_v<TypeC,Subtype>)
369 {
370 OutIndex = 2;
371 OutValuePointer = (PointerType)&Union.Values.C;
372 }
373 else if constexpr (std::is_same_v<TypeD,Subtype>)
374 {
375 OutIndex = 3;
376 OutValuePointer = (PointerType)&Union.Values.D;
377 }
378 else if constexpr (std::is_same_v<TypeE,Subtype>)
379 {
380 OutIndex = 4;
381 OutValuePointer = (PointerType)&Union.Values.E;
382 }
383 else if constexpr (std::is_same_v<TypeF,Subtype>)
384 {
385 OutIndex = 5;
386 OutValuePointer = (PointerType)&Union.Values.F;
387 }
388 else
389 {
390 static_assert(sizeof(TypeA) == 0, "Type is not subtype of union.");
391 OutIndex = (uint8)-1;
393 }
394 }
395
396 static void FatalErrorUndefinedSubtype()
397 {
398 UE_LOG(LogUnion, Fatal, TEXT("Unrecognized TUnion subtype"));
399 }
400};
401
402template<typename TypeA,typename TypeB,typename TypeC,typename TypeD,typename TypeE,typename TypeF>
#define NULL
Definition oodle2base.h:134
#define check(expr)
Definition AssertionMacros.h:314
FArchive & operator<<(FArchive &Ar, TUnion< TypeA, TypeB, TypeC, TypeD, TypeE, TypeF > &Union)
Definition Union.h:403
#define TEXT(x)
Definition Platform.h:1272
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define DECLARE_LOG_CATEGORY_EXTERN(CategoryName, DefaultVerbosity, CompileTimeVerbosity)
Definition LogMacros.h:361
#define UE_LOG(CategoryName, Verbosity, Format,...)
Definition LogMacros.h:270
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Archive.h:1208
virtual void Serialize(void *V, int64 Length)
Definition Archive.h:1689
UE_FORCEINLINE_HINT bool IsLoading() const
Definition Archive.h:236
Definition Union.h:29
friend FArchive & operator<<(FArchive &Ar, FNull &Value)
Definition Union.h:47
bool operator!=(const FNull &) const
Definition Union.h:42
friend uint32 GetTypeHash(FNull)
Definition Union.h:32
bool operator==(const FNull &) const
Definition Union.h:37
Definition Union.h:64
bool operator==(const TUnion &Other) const
Definition Union.h:271
TUnion(const TUnion &Other)
Definition Union.h:108
TUnion & operator=(const TUnion &Other)
Definition Union.h:252
TUnion(typename TCallTraits< TypeE >::ParamType InValue, TDisambiguater< 4 > Disambiguater=TDisambiguater< 4 >())
Definition Union.h:96
TUnion()
Definition Union.h:68
TUnion(typename TCallTraits< TypeD >::ParamType InValue, TDisambiguater< 3 > Disambiguater=TDisambiguater< 3 >())
Definition Union.h:90
Subtype & GetSubtype()
Definition Union.h:168
TUnion(typename TCallTraits< TypeA >::ParamType InValue, TDisambiguater< 0 > Disambiguater=TDisambiguater< 0 >())
Definition Union.h:72
TUnion(typename TCallTraits< TypeF >::ParamType InValue, TDisambiguater< 5 > Disambiguater=TDisambiguater< 5 >())
Definition Union.h:102
TTypeCompatibleBytes< TypeC > C
Definition Union.h:333
void ResetSubtype()
Definition Union.h:134
TUnion(typename TCallTraits< TypeC >::ParamType InValue, TDisambiguater< 2 > Disambiguater=TDisambiguater< 2 >())
Definition Union.h:84
~TUnion()
Definition Union.h:114
void Serialize(FArchive &Ar)
Definition Union.h:290
TTypeCompatibleBytes< TypeF > F
Definition Union.h:336
TTypeCompatibleBytes< TypeE > E
Definition Union.h:335
const Subtype & GetSubtype() const
Definition Union.h:153
Subtype * SetSubtype(typename TCallTraits< Subtype >::ParamType NewValue)
Definition Union.h:199
bool HasSubtype() const
Definition Union.h:122
uint8 GetCurrentSubtypeIndex() const
Definition Union.h:214
void Reset()
Definition Union.h:220
friend uint32 GetTypeHash(const TUnion &Union)
Definition Union.h:234
Subtype * SetSubtype()
Definition Union.h:183
TUnion(typename TCallTraits< TypeB >::ParamType InValue, TDisambiguater< 1 > Disambiguater=TDisambiguater< 1 >())
Definition Union.h:78
TTypeCompatibleBytes< TypeA > A
Definition Union.h:331
TTypeCompatibleBytes< TypeB > B
Definition Union.h:332
TTypeCompatibleBytes< TypeD > D
Definition Union.h:334
TCallTraitsParamTypeHelper< T, PassByValue >::ParamType ParamType
Definition UnrealTypeTraits.h:275
Definition Union.h:23
TDisambiguater()
Definition Union.h:24
Definition TypeCompatibleBytes.h:24