UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
TVariant.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
6#include "TVariantMeta.h"
7#include <type_traits>
8
12template <typename T>
13struct TInPlaceType {};
14
19namespace UE::Core::Private
20{
21template <typename T>
23}
24
29{
32 {
33 return Ar;
34 }
35};
36
41template <typename T, typename... Ts>
42class TVariant final
44 : private UE::Core::Private::TVariantStorage<T, Ts...>
45#else
46 : private std::conditional_t<!std::is_trivially_destructible_v<T> || (!std::is_trivially_destructible_v<Ts> || ...), UE::Core::Private::TDestructibleVariantStorage<T, Ts...> , UE::Core::Private::TVariantStorage<T, Ts...>>
47#endif
48{
49#if PLATFORM_COMPILER_SUPPORTS_CONSTRAINED_DESTRUCTORS
50 using Super = UE::Core::Private::TVariantStorage<T, Ts...>;
51#else
52 using Super = std::conditional_t<!std::is_trivially_destructible_v<T> || (!std::is_trivially_destructible_v<Ts> || ...), UE::Core::Private::TDestructibleVariantStorage<T, Ts...> , UE::Core::Private::TVariantStorage<T, Ts...>>;
53#endif
54
55 static_assert(!UE::Core::Private::TTypePackContainsDuplicates<T, Ts...>::Value, "All the types used in TVariant should be unique");
56 static_assert(!UE::Core::Private::TContainsReferenceType<T, Ts...>::Value, "TVariant cannot hold reference types");
57
58 // Test for 255 here, because the parameter pack doesn't include the initial T
59 static_assert(sizeof...(Ts) <= 255, "TVariant cannot hold more than 256 types");
60
61public:
64 {
65 static_assert(std::is_constructible_v<T>, "To default-initialize a TVariant, the first type in the parameter pack must be default constructible. Use FEmptyVariantState as the first type if none of the other types can be listed first.");
66 ::new((void*)&UE::Core::Private::CastToStorage(*this).Storage) T();
67 TypeIndex = 0;
68 }
69
71 template <
72 typename U,
73 typename... ArgTypes
74 UE_REQUIRES(std::is_constructible_v<U, ArgTypes...>)
75 >
76 [[nodiscard]] explicit TVariant(TInPlaceType<U>&&, ArgTypes&&... Args)
77 {
79 static_assert(Index != (SIZE_T)-1, "The TVariant is not declared to hold the type being constructed");
80
81 ::new((void*)&UE::Core::Private::CastToStorage(*this).Storage) U(Forward<ArgTypes>(Args)...);
82 TypeIndex = (uint8)Index;
83 }
84
91
98
101 {
102 if (&Other != this)
103 {
104 TVariant Temp = Other;
105 Swap(Temp, *this);
106 }
107 return *this;
108 }
109
112 {
113 if (&Other != this)
114 {
115 TVariant Temp = MoveTemp(Other);
116 Swap(Temp, *this);
117 }
118 return *this;
119 }
120
121#if PLATFORM_COMPILER_SUPPORTS_CONSTRAINED_DESTRUCTORS
123 ~TVariant()
124 requires(!std::is_trivially_destructible_v<T> || (!std::is_trivially_destructible_v<Ts> || ...))
125 {
127 }
128 ~TVariant()
129 requires(std::is_trivially_destructible_v<T> && (std::is_trivially_destructible_v<Ts> && ...))
130 = default;
131#else
132 // Defer to the storage as to how to destruct the elements
133 ~TVariant() = default;
134#endif
135
137 template <typename U>
138 [[nodiscard]] bool IsType() const
139 {
140 static_assert(UE::Core::Private::TParameterPackTypeIndex<U, T, Ts...>::Value != (SIZE_T)-1, "The TVariant is not declared to hold the type passed to IsType<>");
142 }
143
145 template <typename U>
147 {
149 static_assert(Index != (SIZE_T)-1, "The TVariant is not declared to hold the type passed to Get<>");
150
151 check(Index == TypeIndex);
152 // The intermediate step of casting to void* is used to avoid warnings due to use of reinterpret_cast between related types if U and the storage class are related
153 // This was specifically encountered when U derives from TAlignedBytes
154 return *reinterpret_cast<U*>(reinterpret_cast<void*>(&UE::Core::Private::CastToStorage(*this).Storage));
155 }
156
158 template <typename U>
159 [[nodiscard]] const U& Get() const UE_LIFETIMEBOUND
160 {
161 // Temporarily remove the const qualifier so we can implement Get in one location.
162 return const_cast<TVariant*>(this)->template Get<U>();
163 }
164
166 template <typename U>
167 const U& Get(const TIdentity_T<U>& DefaultValue UE_LIFETIMEBOUND) const UE_LIFETIMEBOUND
168 {
169 return IsType<U>() ? Get<U>() : DefaultValue;
170 }
171
173 template <typename U>
175 {
177 static_assert(Index != (SIZE_T)-1, "The TVariant is not declared to hold the type passed to TryGet<>");
178 // The intermediate step of casting to void* is used to avoid warnings due to use of reinterpret_cast between related types if U and the storage class are related
179 // This was specifically encountered when U derives from TAlignedBytes
180 return Index == (SIZE_T)TypeIndex ? reinterpret_cast<U*>(reinterpret_cast<void*>(&UE::Core::Private::CastToStorage(*this).Storage)) : nullptr;
181 }
182
184 template <typename U>
185 [[nodiscard]] const U* TryGet() const UE_LIFETIMEBOUND
186 {
187 // Temporarily remove the const qualifier so we can implement TryGet in one location.
188 return const_cast<TVariant*>(this)->template TryGet<U>();
189 }
190
192 template <typename U>
193 void Set(typename TIdentity<U>::Type&& Value)
194 {
196 }
197
199 template <typename U>
200 void Set(const typename TIdentity<U>::Type& Value)
201 {
203 }
204
206 template <
207 typename U,
208 typename... ArgTypes
209 UE_REQUIRES(std::is_constructible_v<U, ArgTypes...>)
210 >
211 void Emplace(ArgTypes&&... Args)
212 {
214 static_assert(Index != (SIZE_T)-1, "The TVariant is not declared to hold the type passed to Emplace<>");
215
217 ::new((void*)&UE::Core::Private::CastToStorage(*this).Storage) U(Forward<ArgTypes>(Args)...);
218 TypeIndex = (uint8)Index;
219 }
220
222 template <typename U>
223 [[nodiscard]] static constexpr SIZE_T IndexOfType()
224 {
226 static_assert(Index != (SIZE_T)-1, "The TVariant is not declared to hold the type passed to IndexOfType<>");
227 return Index;
228 }
229
232 {
233 return (SIZE_T)TypeIndex;
234 }
235
248 template <typename U>
250 {
252 static_assert(Index != (SIZE_T)-1, "The TVariant is not declared to store the specified type");
253 TypeIndex = (uint8)Index;
254 }
255
256private:
257#if PLATFORM_COMPILER_SUPPORTS_CONSTRAINED_DESTRUCTORS
259 uint8 TypeIndex;
260#else
261 using Super::TypeIndex;
262#endif
263};
264
266template <
267 typename Func,
268 typename... Variants
269 UE_REQUIRES((TIsVariant_V<std::decay_t<Variants>> && ...))
270>
271decltype(auto) Visit(Func&& Callable, Variants&&... Args)
272{
274
277 Forward<Func>(Callable),
279 TMakeIntegerSequence<SIZE_T, sizeof...(Variants)>{},
280 Forward<Variants>(Args)...
281 );
282}
283
291template <typename... Ts>
293{
294 if (Ar.IsLoading())
295 {
296 uint8 Index;
297 Ar << Index;
298 check(Index < sizeof...(Ts));
299
301 }
302 else
303 {
304 uint8 Index = (uint8)Variant.GetIndex();
305 Ar << Index;
306 Visit([&Ar](auto& StoredValue)
307 {
308 Ar << StoredValue;
309 }, Variant);
310 }
311 return Ar;
312}
#define check(expr)
Definition AssertionMacros.h:314
#define PLATFORM_COMPILER_SUPPORTS_CONSTRAINED_DESTRUCTORS
Definition Platform.h:290
#define UE_LIFETIMEBOUND
Definition Platform.h:812
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
typename TIdentity< T >::Type TIdentity_T
Definition Identity.h:24
typename UE4IntegerSequence_Private::TMakeIntegerSequenceImpl< T, N >::Type TMakeIntegerSequence
Definition IntegerSequence.h:31
#define UE_REQUIRES(...)
Definition Requires.h:86
constexpr bool TIsVariant_V
Definition TVariantMeta.h:19
FArchive & operator<<(typename UE::Core::Private::TAlwaysFArchive< TVariant< Ts... > >::Type &Ar, TVariant< Ts... > &Variant)
Definition TVariant.h:292
decltype(auto) Visit(Func &&Callable, Variants &&... Args)
Definition TVariant.h:271
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
if(Failed) console_printf("Failed.\n")
uint8_t uint8
Definition binka_ue_file_header.h:8
Definition Archive.h:1208
Definition TVariant.h:48
static constexpr SIZE_T IndexOfType()
Definition TVariant.h:223
void Emplace(ArgTypes &&... Args)
Definition TVariant.h:211
const U * TryGet() const UE_LIFETIMEBOUND
Definition TVariant.h:185
const U & Get(const TIdentity_T< U > &DefaultValue UE_LIFETIMEBOUND) const UE_LIFETIMEBOUND
Definition TVariant.h:167
TVariant(const TVariant &Other)
Definition TVariant.h:86
U & Get() UE_LIFETIMEBOUND
Definition TVariant.h:146
TVariant()
Definition TVariant.h:63
TVariant(TVariant &&Other)
Definition TVariant.h:93
void Set(typename TIdentity< U >::Type &&Value)
Definition TVariant.h:193
U * TryGet() UE_LIFETIMEBOUND
Definition TVariant.h:174
void Set(const typename TIdentity< U >::Type &Value)
Definition TVariant.h:200
const U & Get() const UE_LIFETIMEBOUND
Definition TVariant.h:159
~TVariant()=default
TVariant(TInPlaceType< U > &&, ArgTypes &&... Args)
Definition TVariant.h:76
TVariant & operator=(const TVariant &Other)
Definition TVariant.h:100
bool IsType() const
Definition TVariant.h:138
TVariant(UE::Core::Private::TUninitializedType< U > &&)
Definition TVariant.h:249
SIZE_T GetIndex() const
Definition TVariant.h:231
TVariant & operator=(TVariant &&Other)
Definition TVariant.h:111
implementation
Definition PlayInEditorLoadingScope.h:8
SIZE_T EncodeIndices(const T &Variant)
Definition TVariantMeta.h:310
decltype(auto) VisitImpl(SIZE_T EncodedIndex, Func &&Callable, TIntegerSequence< SIZE_T, EncodedIndices... > &&, TIntegerSequence< SIZE_T, VariantIndices... > &&VariantIndicesSeq, Variants &&... Args)
Definition TVariantMeta.h:377
UE_FORCEINLINE_HINT TVariantStorage< Ts... > & CastToStorage(TVariant< Ts... > &Variant)
Definition TVariantMeta.h:335
U16 Index
Definition radfft.cpp:71
Definition TVariant.h:29
friend FArchive & operator<<(FArchive &Ar, FEmptyVariantState &)
Definition TVariant.h:31
T Type
Definition Identity.h:19
Definition TVariant.h:13
Definition TVariantMeta.h:63
Definition TVariantMeta.h:98
static void Construct(SIZE_T TypeIndex, void *Storage, const void *Value)
Definition TVariantMeta.h:233
static void Destruct(SIZE_T TypeIndex, void *Value)
Definition TVariantMeta.h:209
static bool IsSame(SIZE_T TypeIndex)
Definition TVariantMeta.h:300
static void Construct(SIZE_T TypeIndex, void *Target, void *Source)
Definition TVariantMeta.h:258
Definition TVariantMeta.h:190
static void Load(SIZE_T TypeIndex, FArchive &Ar, VariantType &OutVariant)
Definition TVariantMeta.h:287
Definition TVariantMeta.h:105