UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
NotNull.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"
7#include "Misc/UEOps.h"
11
12#include <type_traits>
13
39#ifndef UE_ENABLE_NOTNULL_WRAPPER
40 #define UE_ENABLE_NOTNULL_WRAPPER (UE_BUILD_DEBUG || UE_BUILD_DEVELOPMENT)
41#endif
42
43#ifdef __clang__
44 // Disable clang warnings about returns_nonnull only being applicable to raw pointers
45 #define UE_NOTNULL_FUNCTION_NON_NULL_RETURN_START _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wignored-attributes\"") FUNCTION_NON_NULL_RETURN_START _Pragma("clang diagnostic pop")
46 #define UE_NOTNULL_FUNCTION_NON_NULL_RETURN_END _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wignored-attributes\"") FUNCTION_NON_NULL_RETURN_END _Pragma("clang diagnostic pop")
47#else
48 #define UE_NOTNULL_FUNCTION_NON_NULL_RETURN_START FUNCTION_NON_NULL_RETURN_START
49 #define UE_NOTNULL_FUNCTION_NON_NULL_RETURN_END FUNCTION_NON_NULL_RETURN_END
50#endif
51
52#if UE_ENABLE_NOTNULL_WRAPPER
53
54 class FArchive;
55
56 template <typename T>
57 struct TNotNull;
58
59 namespace UE::Core::Private
60 {
61#if DO_CHECK
62 template <typename T, typename = void>
64 {
65 static constexpr bool Value = false;
66 };
67
68 template <typename T>
69 struct TSupportsNotOperator<T, std::void_t<decltype(!std::declval<T>())>>
70 {
71 static constexpr bool Value = true;
72 };
73
74 template <typename T>
75 inline constexpr bool TSupportsNotOperator_V = TSupportsNotOperator<T>::Value;
76
79#endif // DO_CHECK
80
81 template <typename... ArgTypes>
82 struct TIsTNotNullParam
83 {
84 static constexpr bool Value = false;
85 };
86
87 template <typename T>
88 struct TIsTNotNullParam<TNotNull<T>>
89 {
90 static constexpr bool Value = true;
91 };
92
93 template <typename... ArgTypes>
94 inline constexpr bool TIsTNotNullParam_V = TIsTNotNullParam<ArgTypes...>::Value;
95
96 template <typename T>
97 struct TNotNullBase
98 {
99 using Sub = TNotNull<T>;
100
101 // Allow implicit conversion to the wrapped value, for compatibility with non-TNotNull APIs
102 operator T() const&
103 {
104 return ((Sub*)this)->Val;
105 }
106 operator T() &&
107 {
108 return (T&&)((Sub*)this)->Val;
109 }
110
111 // Allow dereferencing, if it's supported
112 const T& operator->() const
113 {
114 return ((Sub*)this)->Val;
115 }
116 };
117
118 template <typename T>
119 struct TNotNullBase<T*>
120 {
121 using Sub = TNotNull<T*>;
122
123 // Allow implicit conversion to the wrapped value, for compatibility with non-TNotNull APIs
125 operator T*() const
127 {
128 return ((Sub*)this)->Val;
129 }
130
131 // Allow dereferencing, if it's supported
133 T* operator->() const
135 {
136 return ((Sub*)this)->Val;
137 }
138 };
139 }
140
141 template <typename T>
142 struct TNotNull : UE::Core::Private::TNotNullBase<T>
143 {
144 private:
145 using Super = UE::Core::Private::TNotNullBase<T>;
146 friend Super;
147
148 T Val;
149
150 public:
151 template <typename>
152 friend struct TNotNull;
153
154 // Prevent default construction and construction/assignment against nullptr
155 TNotNull() = delete;
156 TNotNull(TYPE_OF_NULLPTR) = delete;
157 TNotNull& operator=(TYPE_OF_NULLPTR) = delete;
158 ~TNotNull() = default;
159
160 // Allow direct construction of the inner value
161 template <typename... ArgTypes>
162 requires (std::is_constructible_v<T, ArgTypes...> && !UE::Core::Private::TIsTNotNullParam_V<std::decay_t<ArgTypes>...>)
164 : Val((ArgTypes&&)Args...)
165 {
166#if DO_CHECK
167 if constexpr (UE::Core::Private::TSupportsNotOperator_V<T>)
168 {
169 if (!Val)
170 {
171 UE::Core::Private::ReportNotNullPtr();
172 }
173 }
174#endif
175 }
176
178 // Start - intrusive TOptional<TNotNull> state //
180 static constexpr bool bHasIntrusiveUnsetOptionalState = HasIntrusiveUnsetOptionalState<T>();
181 using IntrusiveUnsetOptionalStateType = TNotNull;
182
184 requires(bHasIntrusiveUnsetOptionalState)
185 : Val(Tag)
186 {
187 }
189 requires(bHasIntrusiveUnsetOptionalState)
190 {
191 return Val == Tag;
192 }
194 // End - intrusive TOptional<TNotNull> state //
196
197 // Allow conversions
198 template <
199 typename OtherType
200 UE_REQUIRES(std::is_convertible_v<const OtherType&, T>)
201 >
202 TNotNull(const TNotNull<OtherType>& Rhs)
203 : Val(Rhs.Val)
204 {
205 }
206 template <
207 typename OtherType
208 UE_REQUIRES(std::is_convertible_v<OtherType&&, T>)
209 >
211 : Val((OtherType&&)Rhs.Val)
212 {
213 }
214
215 // Forward copying and moving to the inner type
216 TNotNull(TNotNull&&) = default;
217 TNotNull(const TNotNull&) = default;
218 TNotNull& operator=(TNotNull&&) = default;
219 TNotNull& operator=(const TNotNull&) = default;
220
221 // Disallow testing for nullness - implicitly or explicitly
222 operator bool() const = delete;
223
224 // Allow dereferencing, if it's supported
225 decltype(auto) operator*() const
226 {
227 return *Val;
228 }
229
230 // Allow function call syntax, if it's supported
231 template <typename... ArgTypes>
232 auto operator()(ArgTypes&&... Args) const -> decltype(this->Val((ArgTypes&&)Args...))
233 {
234 return Val((ArgTypes&&)Args...);
235 }
236
237 // Allow hashing, if it's supported
238 friend uint32 GetTypeHash(const TNotNull& NotNull)
239 {
240 return GetTypeHashHelper(NotNull.Val);
241 }
242
243 // Allow comparison, if it's supported
244 template <typename U>
245 [[nodiscard]] auto UEOpEquals(const TNotNull<U>& Rhs) const -> decltype(Val == Rhs.Val)
246 {
247 return Val == Rhs.Val;
248 }
249 template <typename U>
250 [[nodiscard]] auto UEOpEquals(const U& Rhs) const -> decltype(Val == Rhs)
251 {
252 static_assert(!std::is_same_v<U, TYPE_OF_NULLPTR>, "Comparing a TNotNull to nullptr is illegal");
253 return Val == Rhs;
254 }
255
256 // Disallow comparison against nullptr
257 bool UEOpEquals(TYPE_OF_NULLPTR Rhs) const = delete;
258 };
259
260 // Allow serialization, if it's supported
261 template <typename T>
262 auto operator<<(FArchive& Ar, TNotNull<T>& Val) -> decltype(Ar << (T&)Val)
263 {
264 if constexpr (std::is_void_v<decltype(Ar << (T&)Val)>)
265 {
266 Ar << (T&)Val;
267 if constexpr (UE::Core::Private::TSupportsNotOperator_V<T>)
268 {
269 if (!(T&)Val)
270 {
271 UE::Core::Private::CheckLoadingNotNullPtr(Ar);
272 }
273 }
274 }
275 else
276 {
277 decltype(auto) Result = Ar << (T&)Val;
278 if constexpr (UE::Core::Private::TSupportsNotOperator_V<T>)
279 {
280 if (!(T&)Val)
281 {
282 UE::Core::Private::CheckLoadingNotNullPtr(Ar);
283 }
284 }
285 return Result;
286 }
287 }
288
289 // Gets the inner value of a TNotNull without requiring a cast and repeat its inner type.
290 template <typename T>
292 {
293 return NotNull;
294 }
295 template <typename T>
297 {
298 return (TNotNull<T>&&)NotNull;
299 }
300
301#undef UE_NOTNULL_FUNCTION_NON_NULL_RETURN_END
302#undef UE_NOTNULL_FUNCTION_NON_NULL_RETURN_START
303
304#else // UE_ENABLE_NOTNULL_WRAPPER
305
306 template <typename T>
307 using TNotNull = T;
308
309 // Gets the inner value of a TNotNull without requiring a cast and repeat its inner type.
310 template <typename T>
312 {
313 return (T&&)NotNull;
314 }
315
316#endif // !UE_ENABLE_NOTNULL_WRAPPER
#define CA_NO_RETURN
Definition CoreMiscDefines.h:124
FPlatformTypes::TYPE_OF_NULLPTR TYPE_OF_NULLPTR
The type of the C++ nullptr keyword.
Definition Platform.h:1157
#define UE_NODEBUG
Definition Platform.h:817
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
FArchive & operator<<(FArchive &Ar, FEnvQueryDebugProfileData::FStep &Data)
Definition EnvQueryTypes.cpp:489
T && NotNullGet(T &&NotNull)
Definition NotNull.h:311
#define UE_NOTNULL_FUNCTION_NON_NULL_RETURN_START
Definition NotNull.h:48
T TNotNull
Definition NotNull.h:307
#define UE_NOTNULL_FUNCTION_NON_NULL_RETURN_END
Definition NotNull.h:49
const bool
Definition NetworkReplayStreaming.h:178
#define UE_REQUIRES(...)
Definition Requires.h:86
UE_FORCEINLINE_HINT uint32 GetTypeHashHelper(const T &V)
Definition TypeHash.h:215
float Val(const FString &Value)
Definition UnrealMath.cpp:3163
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Archive.h:1208
uint32 GetTypeHash(const FKey &Key)
Definition BlackboardKey.h:35
bool operator==(const FCachedAssetKey &A, const FCachedAssetKey &B)
Definition AssetDataMap.h:501
implementation
Definition PlayInEditorLoadingScope.h:8
FORCEINLINE UE_STRING_CLASS RhsType && Rhs
Definition String.cpp.inl:718
UE_STRING_CLASS Result(Forward< LhsType >(Lhs), RhsLen)
Definition String.cpp.inl:732
Definition IntrusiveUnsetOptionalState.h:71