UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
MemoryOps.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/UnrealMemory.h"
9#include <new> // IWYU pragma: export
10#include <type_traits>
11
12
14{
15 template <typename DestinationElementType, typename SourceElementType>
16 constexpr inline bool TCanBitwiseRelocate_V =
17 std::is_same_v<DestinationElementType, SourceElementType> || (
19 std::is_trivially_destructible_v<SourceElementType>
20 );
21}
22
29template <typename ElementType, typename SizeType>
30 requires (sizeof(ElementType) > 0 && !!TIsZeroConstructType<ElementType>::Value) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
31FORCEINLINE void DefaultConstructItems(void* Address, SizeType Count)
32{
33 FMemory::Memset(Address, 0, sizeof(ElementType) * Count);
34}
35template <typename ElementType, typename SizeType>
36 requires (sizeof(ElementType) > 0 && !TIsZeroConstructType<ElementType>::Value) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
37FORCENOINLINE void DefaultConstructItems(void* Address, SizeType Count)
38{
39 ElementType* Element = (ElementType*)Address;
40 while (Count)
41 {
42 ::new ((void*)Element) ElementType;
43 ++Element;
44 --Count;
45 }
46}
47
55template <typename ElementType>
56FORCEINLINE constexpr void DestructItem(ElementType* Element)
57{
58 if constexpr (sizeof(ElementType) == 0)
59 {
60 // Should never get here, but this construct should improve the error messages we get when we try to call this function with incomplete types
61 }
62 else if constexpr (!std::is_trivially_destructible_v<ElementType>)
63 {
64 // We need a typedef here because VC won't compile the destructor call below if ElementType itself has a member called ElementType
65 typedef ElementType DestructItemsElementTypeTypedef;
66
67 Element->DestructItemsElementTypeTypedef::~DestructItemsElementTypeTypedef();
68 }
69}
70
79template <typename ElementType, typename SizeType>
80 requires (sizeof(ElementType) > 0 && std::is_trivially_destructible_v<ElementType>) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
81FORCEINLINE constexpr void DestructItems(ElementType* Element, SizeType Count)
82{
83}
84template <typename ElementType, typename SizeType>
85 requires (sizeof(ElementType) > 0 && !std::is_trivially_destructible_v<ElementType>) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
86FORCENOINLINE constexpr void DestructItems(ElementType* Element, SizeType Count)
87{
88 while (Count)
89 {
90 // We need a typedef here because VC won't compile the destructor call below if ElementType itself has a member called ElementType
91 typedef ElementType DestructItemsElementTypeTypedef;
92
93 Element->DestructItemsElementTypeTypedef::~DestructItemsElementTypeTypedef();
94 ++Element;
95 --Count;
96 }
97}
98
106template <typename DestinationElementType, typename SourceElementType, typename SizeType>
107 requires (sizeof(DestinationElementType) > 0 && sizeof(SourceElementType) > 0 && !!TIsBitwiseConstructible<DestinationElementType, SourceElementType>::Value) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
108FORCEINLINE void ConstructItems(void* Dest, const SourceElementType* Source, SizeType Count)
109{
110 if (Count)
111 {
112 FMemory::Memcpy(Dest, Source, sizeof(SourceElementType) * Count);
113 }
114}
115template <typename DestinationElementType, typename SourceElementType, typename SizeType>
116 requires (sizeof(DestinationElementType) > 0 && sizeof(SourceElementType) > 0 && !TIsBitwiseConstructible<DestinationElementType, SourceElementType>::Value) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
117FORCENOINLINE void ConstructItems(void* Dest, const SourceElementType* Source, SizeType Count)
118{
119 while (Count)
120 {
121 ::new ((void*)Dest) DestinationElementType(*Source);
122 ++(DestinationElementType*&)Dest;
123 ++Source;
124 --Count;
125 }
126}
127
135template <typename ElementType, typename SizeType>
136 requires (sizeof(ElementType) > 0 && std::is_trivially_copy_assignable_v<ElementType>) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
137FORCEINLINE void CopyAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count)
138{
139 FMemory::Memcpy(Dest, Source, sizeof(ElementType) * Count);
140}
141template <typename ElementType, typename SizeType>
142 requires (sizeof(ElementType) > 0 && !std::is_trivially_copy_assignable_v<ElementType>) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
143FORCENOINLINE void CopyAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count)
144{
145 while (Count)
146 {
147 *Dest = *Source;
148 ++Dest;
149 ++Source;
150 --Count;
151 }
152}
153
161template <typename DestinationElementType, typename SourceElementType, typename SizeType>
163{
164 if constexpr (sizeof(DestinationElementType) == 0 || sizeof(SourceElementType) == 0)
165 {
166 // Should never get here, but this construct should improve the error messages we get when we try to call this function with incomplete types
167 }
168 // Do a bitwise relocate if TCanBitwiseRelocate_V says we can, but not if the type involved is known not to be bitwise-swappable
169 else if constexpr (UE::Core::Private::MemoryOps::TCanBitwiseRelocate_V<DestinationElementType, SourceElementType> && (!std::is_same_v<DestinationElementType, SourceElementType> || TUseBitwiseSwap<SourceElementType>::Value))
170 {
171 /* All existing UE containers seem to assume trivial relocatability (i.e. memcpy'able) of their members,
172 * so we're going to assume that this is safe here. However, it's not generally possible to assume this
173 * in general as objects which contain pointers/references to themselves are not safe to be trivially
174 * relocated.
175 *
176 * However, it is not yet possible to automatically infer this at compile time, so we can't enable
177 * different (i.e. safer) implementations anyway. */
178
179 FMemory::Memmove(Dest, Source, sizeof(SourceElementType));
180 }
181 else
182 {
183 // We need a typedef here because VC won't compile the destructor call below if SourceElementType itself has a member called SourceElementType
185
186 ::new ((void*)Dest) DestinationElementType(*Source);
187 Source->RelocateConstructItemsElementTypeTypedef::~RelocateConstructItemsElementTypeTypedef();
188 }
189}
190
199template <typename DestinationElementType, typename SourceElementType, typename SizeType>
200 requires (sizeof(DestinationElementType) > 0 && sizeof(SourceElementType) > 0 && UE::Core::Private::MemoryOps::TCanBitwiseRelocate_V<DestinationElementType, SourceElementType>) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
202{
203 static_assert(!std::is_const_v<SourceElementType>, "RelocateConstructItems: Source cannot be const");
204
205 /* All existing UE containers seem to assume trivial relocatability (i.e. memcpy'able) of their members,
206 * so we're going to assume that this is safe here. However, it's not generally possible to assume this
207 * in general as objects which contain pointers/references to themselves are not safe to be trivially
208 * relocated.
209 *
210 * However, it is not yet possible to automatically infer this at compile time, so we can't enable
211 * different (i.e. safer) implementations anyway. */
212
213 FMemory::Memmove(Dest, Source, sizeof(SourceElementType) * Count);
214}
215template <typename DestinationElementType, typename SourceElementType, typename SizeType>
216 requires (sizeof(DestinationElementType) > 0 && sizeof(SourceElementType) > 0 && !UE::Core::Private::MemoryOps::TCanBitwiseRelocate_V<DestinationElementType, SourceElementType>) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
218{
219 static_assert(!std::is_const_v<SourceElementType>, "RelocateConstructItems: Source cannot be const");
220
221 while (Count)
222 {
223 // We need a typedef here because VC won't compile the destructor call below if SourceElementType itself has a member called SourceElementType
225
226 ::new ((void*)Dest) DestinationElementType((SourceElementType&&)*Source);
227 ++(DestinationElementType*&)Dest;
229 --Count;
230 }
231}
232
240template <typename ElementType, typename SizeType>
241 requires (sizeof(ElementType) > 0 && std::is_trivially_copy_constructible_v<ElementType>) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
242FORCEINLINE void MoveConstructItems(void* Dest, const ElementType* Source, SizeType Count)
243{
244 FMemory::Memmove(Dest, Source, sizeof(ElementType) * Count);
245}
246template <typename ElementType, typename SizeType>
247 requires (sizeof(ElementType) > 0 && !std::is_trivially_copy_constructible_v<ElementType>) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
248FORCENOINLINE void MoveConstructItems(void* Dest, const ElementType* Source, SizeType Count)
249{
250 while (Count)
251 {
252 ::new ((void*)Dest) ElementType((ElementType&&)*Source);
253 ++(ElementType*&)Dest;
254 ++Source;
255 --Count;
256 }
257}
258
266template <typename ElementType, typename SizeType>
267 requires (sizeof(ElementType) > 0 && std::is_trivially_copy_assignable_v<ElementType>) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
268FORCEINLINE void MoveAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count)
269{
270 FMemory::Memmove(Dest, Source, sizeof(ElementType) * Count);
271}
272template <typename ElementType, typename SizeType>
273 requires (sizeof(ElementType) > 0 && !std::is_trivially_copy_assignable_v<ElementType>) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
274FORCENOINLINE void MoveAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count)
275{
276 while (Count)
277 {
278 *Dest = (ElementType&&)*Source;
279 ++Dest;
280 ++Source;
281 --Count;
282 }
283}
284
285template <typename ElementType, typename SizeType>
286 requires (sizeof(ElementType) > 0 && !!TTypeTraits<ElementType>::IsBytewiseComparable) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
287FORCEINLINE bool CompareItems(const ElementType* A, const ElementType* B, SizeType Count)
288{
289 return !Count || !FMemory::Memcmp(A, B, sizeof(ElementType) * Count);
290}
291template <typename ElementType, typename SizeType>
292 requires (sizeof(ElementType) > 0 && !TTypeTraits<ElementType>::IsBytewiseComparable) // the sizeof here should improve the error messages we get when we try to call this function with incomplete types
293FORCENOINLINE bool CompareItems(const ElementType* A, const ElementType* B, SizeType Count)
294{
295 while (Count)
296 {
297 if (!(*A == *B))
298 {
299 return false;
300 }
301
302 ++A;
303 ++B;
304 --Count;
305 }
306
307 return true;
308}
309
310#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_7
313#include "Templates/Requires.h"
314#endif
#define FORCENOINLINE
Definition AndroidPlatform.h:142
#define FORCEINLINE
Definition AndroidPlatform.h:140
FORCEINLINE void RelocateConstructItems(void *Dest, SourceElementType *Source, SizeType Count)
Definition MemoryOps.h:201
FORCEINLINE void RelocateConstructItem(void *Dest, const SourceElementType *Source)
Definition MemoryOps.h:162
FORCEINLINE constexpr void DestructItem(ElementType *Element)
Definition MemoryOps.h:56
FORCEINLINE constexpr void DestructItems(ElementType *Element, SizeType Count)
Definition MemoryOps.h:81
FORCEINLINE void MoveConstructItems(void *Dest, const ElementType *Source, SizeType Count)
Definition MemoryOps.h:242
FORCEINLINE void DefaultConstructItems(void *Address, SizeType Count)
Definition MemoryOps.h:31
FORCEINLINE bool CompareItems(const ElementType *A, const ElementType *B, SizeType Count)
Definition MemoryOps.h:287
FORCEINLINE void MoveAssignItems(ElementType *Dest, const ElementType *Source, SizeType Count)
Definition MemoryOps.h:268
FORCEINLINE void CopyAssignItems(ElementType *Dest, const ElementType *Source, SizeType Count)
Definition MemoryOps.h:137
FORCEINLINE void ConstructItems(void *Dest, const SourceElementType *Source, SizeType Count)
Definition MemoryOps.h:108
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
Definition MemoryOps.h:14
constexpr bool TCanBitwiseRelocate_V
Definition MemoryOps.h:16
static UE_FORCEINLINE_HINT void * Memmove(void *Dest, const void *Src, SIZE_T Count)
Definition UnrealMemory.h:109
static UE_FORCEINLINE_HINT int32 Memcmp(const void *Buf1, const void *Buf2, SIZE_T Count)
Definition UnrealMemory.h:114
static UE_FORCEINLINE_HINT void * Memcpy(void *Dest, const void *Src, SIZE_T Count)
Definition UnrealMemory.h:160
static UE_FORCEINLINE_HINT void * Memset(void *Dest, uint8 Char, SIZE_T Count)
Definition UnrealMemory.h:119
Definition UnrealTypeTraits.h:410
Definition UnrealTypeTraits.h:172
Definition UnrealTypeTraits.h:347
Definition UseBitwiseSwap.h:13