UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Deque.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 "IteratorAdapter.h"
10#include "Templates/MemoryOps.h"
12
13#include <initializer_list>
14
15template <typename InElementType, typename InAllocatorType = FDefaultAllocator>
16class TDeque;
17
18namespace UE
19{
20namespace Deque
21{
22namespace Private
23{
28template <typename InSizeType>
30{
31 return (Index < Range) ? Index : Index - Range;
32}
33
37template <typename InElementType, typename InSizeType>
39{
40public:
43
44 TIteratorBase() = default;
45
46protected:
51 : Data(Data), Range(Range), Offset(Offset)
52 {
53 }
54
56 {
57 return *(Data + WrapAround(Offset, Range));
58 }
59
60 inline void Increment()
61 {
62 checkSlow(Offset + 1 < Range * 2); // See WrapAround
63 Offset++;
64 }
65
67 {
68 return Data + Offset == Other.Data + Other.Offset;
69 }
70
71private:
72 ElementType* Data = nullptr;
73 SizeType Range = 0;
74 SizeType Offset = 0;
75};
76
77template <typename InElementType, typename InSizeType>
79} // namespace Private
80} // namespace Deque
81} // namespace UE
82
88template <typename InElementType, typename InAllocatorType>
89class TDeque
90{
91 template <typename AnyElementType, typename AnyAllocatorType>
92 friend class TDeque;
93
94public:
96 using SizeType = typename InAllocatorType::SizeType;
98
99 using ElementAllocatorType = std::conditional_t<
100 AllocatorType::NeedsElementType,
101 typename AllocatorType::template ForElementType<ElementType>,
102 typename AllocatorType::ForAnyElementType>;
103
106
107 [[nodiscard]] TDeque() : Capacity(Storage.GetInitialCapacity())
108 {
109 }
110
112 {
113 MoveUnchecked(MoveTemp(Other));
114 }
115
117 : Capacity(Storage.GetInitialCapacity())
118 {
119 CopyUnchecked(Other);
120 }
121
122 [[nodiscard]] TDeque(std::initializer_list<ElementType> InList)
123 : Capacity(Storage.GetInitialCapacity())
124 {
125 CopyUnchecked(InList);
126 }
127
129 {
130 UE_STATIC_ASSERT_WARN(TIsTriviallyRelocatable_V<InElementType>, "TArray can only be used with trivially relocatable types");
131
132 Empty();
133 }
134
136 {
137 if (this != &Other)
138 {
139 Reset();
140 MoveUnchecked(MoveTemp(Other));
141 }
142 return *this;
143 }
144
146 {
147 if (this != &Other)
148 {
149 Reset();
150 CopyUnchecked(Other);
151 }
152 return *this;
153 }
154
155 TDeque& operator=(std::initializer_list<ElementType> InList)
156 {
157 Reset();
158 CopyUnchecked(InList);
159 return *this;
160 }
161
163 {
164 CheckValidIndex(Index);
165 return GetData()[UE::Deque::Private::WrapAround(Head + Index, Capacity)];
166 }
167
169 {
170 CheckValidIndex(Index);
171 return GetData()[UE::Deque::Private::WrapAround(Head + Index, Capacity)];
172 }
173
174 [[nodiscard]] inline const ElementType& Last() const
175 {
176 CheckValidIndex(0);
177 return GetData()[UE::Deque::Private::WrapAround(Tail + Capacity - 1, Capacity)];
178 }
179
181 {
182 CheckValidIndex(0);
183 return GetData()[UE::Deque::Private::WrapAround(Tail + Capacity - 1, Capacity)];
184 }
185
186 [[nodiscard]] inline const ElementType& First() const
187 {
188 CheckValidIndex(0);
189 return GetData()[Head];
190 }
191
193 {
194 CheckValidIndex(0);
195 return GetData()[Head];
196 }
197
199 {
200 return !Count;
201 }
202
204 {
205 return Capacity;
206 }
207
209 {
210 return Count;
211 }
212
220 {
221 return Storage.GetAllocatedSize(Capacity, sizeof(ElementType));
222 }
223
224 /*
225 * Constructs an element in place using the parameter arguments and adds it at the back of the queue.
226 * This method returns a reference to the constructed element.
227 */
228 template <typename... ArgsType>
230 {
231 GrowIfRequired();
232 ElementType* Target = GetData() + Tail;
233 ::new ((void*)Target) ElementType(Forward<ArgsType>(Args)...);
234 Tail = UE::Deque::Private::WrapAround(Tail + 1, Capacity);
235 Count++;
236 return *Target;
237 }
238
239 /*
240 * Constructs an element in place using the parameter arguments and adds it at the front of the queue.
241 * This method returns a reference to the constructed element.
242 */
243 template <typename... ArgsType>
245 {
246 GrowIfRequired();
247 Head = UE::Deque::Private::WrapAround(Head + Capacity - 1, Capacity);
248 ElementType* Target = GetData() + Head;
249 ::new ((void*)Target) ElementType(Forward<ArgsType>(Args)...);
250 Count++;
251 return *Target;
252 }
253
254 /*
255 * Adds the parameter element at the back of the queue.
256 */
258 {
259 EmplaceLast(Element);
260 }
261
263 {
265 }
266
267 /*
268 * Adds the parameter element at the front of the queue.
269 */
271 {
272 EmplaceFirst(Element);
273 }
274
276 {
278 }
279
280 /*
281 * Removes the element at the back of the queue.
282 * This method requires a non-empty queue.
283 */
284 void PopLast()
285 {
286 CheckValidIndex(0);
287 const SizeType NextTail = UE::Deque::Private::WrapAround(Tail + Capacity - 1, Capacity);
288 DestructItem(GetData() + NextTail);
289 Tail = NextTail;
290 Count--;
291 }
292
293 /*
294 * Removes the element at the front of the queue.
295 * This method requires a non-empty queue.
296 */
297 void PopFirst()
298 {
299 CheckValidIndex(0);
300 DestructItem(GetData() + Head);
301 Head = UE::Deque::Private::WrapAround(Head + 1, Capacity);
302 Count--;
303 }
304
305 /*
306 * Removes the element at the back of the queue if existent after copying it to the parameter
307 * out value.
308 */
310 {
311 if (IsEmpty())
312 {
313 return false;
314 }
315 const SizeType NextTail = UE::Deque::Private::WrapAround(Tail + Capacity - 1, Capacity);
317 DestructItem(GetData() + NextTail);
318 Tail = NextTail;
319 Count--;
320 return true;
321 }
322
323 /*
324 * Removes the element at the front of the queue if existent after copying it to the parameter
325 * out value.
326 */
328 {
329 if (IsEmpty())
330 {
331 return false;
332 }
333 OutValue = MoveTempIfPossible(GetData()[Head]);
334 DestructItem(GetData() + Head);
335 Head = UE::Deque::Private::WrapAround(Head + 1, Capacity);
336 Count--;
337 return true;
338 }
339
340 /*
341 * Destroys all contained elements but doesn't release the container's storage.
342 */
343 void Reset()
344 {
345 if (Count)
346 {
347 if (Head < Tail)
348 {
349 DestructItems(GetData() + Head, Count);
350 }
351 else
352 {
353 DestructItems(GetData(), Tail);
354 DestructItems(GetData() + Head, Capacity - Head);
355 }
356 }
357 Head = Tail = Count = 0;
358 }
359
360 /*
361 * Empties the queue effectively destroying all contained elements and releases any acquired storage.
362 */
363 void Empty()
364 {
365 Reset();
366 if (Capacity)
367 {
368 Storage.ResizeAllocation(0, 0, sizeof(ElementType));
369 Capacity = Storage.GetInitialCapacity();
370 }
371 }
372
373 /*
374 * Reserves storage for the parameter element count.
375 */
377 {
378 if (Capacity < InCount)
379 {
380 Grow(Storage.CalculateSlackReserve(InCount, sizeof(ElementType)));
381 }
382 }
383
384 /*
385 * STL IteratorType model compliance methods.
386 */
388 {
389 return GetIterator(Head);
390 }
392 {
393 return GetIterator(Head);
394 }
396 {
397 return GetIterator(Head + Count);
398 }
400 {
401 return GetIterator(Head + Count);
402 }
403
404private:
405 ElementAllocatorType Storage;
406 SizeType Capacity = 0;
407 SizeType Count = 0;
408 SizeType Head = 0;
409 SizeType Tail = 0;
410
411 [[nodiscard]] UE_FORCEINLINE_HINT const ElementType* GetData() const
412 {
413 return (const ElementType*)Storage.GetAllocation();
414 }
415
417 {
418 return (ElementType*)Storage.GetAllocation();
419 }
420
422 {
423 return ConstIteratorType(InPlace, GetData(), Max(), HeadOffset);
424 }
425
427 {
428 return IteratorType(InPlace, GetData(), Max(), HeadOffset);
429 }
430
436 {
437 checkSlow(Capacity < InCapacity);
438 if (Count)
439 {
440 Linearize();
441 }
442 Storage.ResizeAllocation(Count, InCapacity, sizeof(ElementType));
443 Capacity = InCapacity;
444 Head = 0;
445 Tail = Count;
446 }
447
452 void GrowIfRequired()
453 {
454 if (Count == Capacity)
455 {
456 Grow(Storage.CalculateSlackGrow(Count + 1, Capacity, sizeof(ElementType)));
457 }
458 }
459
460 /*
461 * Copies the parameter container into this one.
462 * This method assumes no previously existing content.
463 */
464 void CopyUnchecked(const TDeque& Other)
465 {
466 checkSlow(!Count);
467 if (Other.Count)
468 {
469 Reserve(Other.Count);
470 CopyElements(Other);
471 }
472 else
473 {
474 // Retain any inline capacity.
475 Capacity = Other.Storage.GetInitialCapacity();
476 }
477 }
478
479 void CopyUnchecked(std::initializer_list<ElementType> InList)
480 {
481 const SizeType InCount = static_cast<SizeType>(InList.size());
482 checkSlow(!Count);
483 if (InCount)
484 {
486 ConstructItems<ElementType>(GetData(), &*InList.begin(), InCount);
487 Tail = Count = InCount;
488 }
489 else
490 {
491 Capacity = Storage.GetInitialCapacity();
492 }
493 }
494
495 /*
496 * Moves the parameter container into this one.
497 * This method assumes no previously existing content.
498 */
499 void MoveUnchecked(TDeque&& Other)
500 {
501 checkSlow(!Count);
502 if (Other.Count)
503 {
504 Storage.MoveToEmpty(Other.Storage);
505 Capacity = Other.Capacity;
506 Count = Other.Count;
507 Head = Other.Head;
508 Tail = Other.Tail;
509 Other.Capacity = Other.Storage.GetInitialCapacity();
510 Other.Count = Other.Head = Other.Tail = 0;
511 }
512 else
513 {
514 Capacity = Other.Storage.GetInitialCapacity();
515 }
516 }
517
518 /*
519 * Copies the parameter container elements into this one.
520 * The copied range is linearized.
521 */
522 void CopyElements(const TDeque& Other)
523 {
524 if (Other.Head < Other.Tail)
525 {
526 ConstructItems<ElementType>(GetData(), Other.GetData() + Other.Head, Other.Count);
527 }
528 else
529 {
530 const SizeType HeadToEndOffset = Other.Capacity - Other.Head;
531 ConstructItems<ElementType>(GetData(), Other.GetData() + Other.Head, HeadToEndOffset);
532 ConstructItems<ElementType>(GetData() + HeadToEndOffset, Other.GetData(), Other.Tail);
533 }
534 Count = Other.Count;
535 Head = 0;
536 Tail = UE::Deque::Private::WrapAround(Count, Capacity);
537 }
538
544 void Linearize()
545 {
546 if (Head < Tail)
547 {
548 ShiftElementsLeft(Count);
549 }
550 else
551 {
553 TempStorage.ResizeAllocation(0, Tail, sizeof(ElementType));
554 RelocateConstructItems<ElementType>(TempStorage.GetAllocation(), GetData(), Tail);
555 const SizeType HeadToEndOffset = Capacity - Head;
556 ShiftElementsLeft(HeadToEndOffset);
558 }
559 }
560
564 void ShiftElementsLeft(SizeType InCount)
565 {
566 if (Head == 0)
567 {
568 return;
569 }
570 SizeType Offset = 0;
571 while (Offset < InCount)
572 {
573 const SizeType Step = FMath::Min(Head, InCount - Offset);
574 RelocateConstructItems<ElementType>(GetData() + Offset, GetData() + Head + Offset, Step);
575 Offset += Step;
576 }
577 }
578
579 inline void CheckValidIndex(SizeType Index) const
580 {
581 checkSlow((Count >= 0) & (Capacity >= Count));
582 if constexpr (AllocatorType::RequireRangeCheck)
583 {
584 checkf((Index >= 0) & (Index < Count), TEXT("Parameter index %d exceeds container size %d"), Index, Count);
585 }
586 }
587
588 //---------------------------------------------------------------------------------------------------------------------
589 // TDeque comparison operators
590 //---------------------------------------------------------------------------------------------------------------------
591public:
592 [[nodiscard]] inline bool operator==(const TDeque& Right) const
593 {
594 if (Num() == Right.Num())
595 {
596 auto EndIt = end();
597 auto LeftIt = begin();
598 auto RightIt = Right.begin();
599 while (LeftIt != EndIt)
600 {
601 if (*LeftIt++ != *RightIt++)
602 {
603 return false;
604 }
605 }
606 return true;
607 }
608 return false;
609 }
610
611#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
612 [[nodiscard]] inline bool operator!=(const TDeque& Right) const
613 {
614 return !(*this == Right);
615 }
616#endif
617};
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
#define UE_STATIC_ASSERT_WARN(bExpression, Message)
Definition CoreMiscDefines.h:431
@ InPlace
Definition CoreMiscDefines.h:162
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
FORCEINLINE constexpr void DestructItem(ElementType *Element)
Definition MemoryOps.h:56
FORCEINLINE constexpr void DestructItems(ElementType *Element, SizeType Count)
Definition MemoryOps.h:81
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTempIfPossible(T &&Obj) noexcept
Definition UnrealTemplate.h:538
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32 Offset
Definition VulkanMemory.cpp:4033
Definition Deque.h:90
void Empty()
Definition Deque.h:363
void PopFirst()
Definition Deque.h:297
ElementType & First()
Definition Deque.h:192
void Reserve(SizeType InCount)
Definition Deque.h:376
UE_FORCEINLINE_HINT SizeType Max() const
Definition Deque.h:203
UE_FORCEINLINE_HINT IteratorType begin()
Definition Deque.h:391
UE::Deque::Private::TIterator< const ElementType, SizeType > ConstIteratorType
Definition Deque.h:104
TDeque()
Definition Deque.h:107
UE_FORCEINLINE_HINT void PushLast(const ElementType &Element)
Definition Deque.h:257
bool TryPopFirst(ElementType &OutValue)
Definition Deque.h:327
TDeque & operator=(std::initializer_list< ElementType > InList)
Definition Deque.h:155
std::conditional_t< AllocatorType::NeedsElementType, typename AllocatorType::template ForElementType< ElementType >, typename AllocatorType::ForAnyElementType > ElementAllocatorType
Definition Deque.h:102
InAllocatorType AllocatorType
Definition Deque.h:95
InElementType ElementType
Definition Deque.h:97
ElementType & EmplaceFirst(ArgsType &&... Args)
Definition Deque.h:244
bool TryPopLast(ElementType &OutValue)
Definition Deque.h:309
TDeque & operator=(const TDeque &Other)
Definition Deque.h:145
ElementType & Last()
Definition Deque.h:180
UE_FORCEINLINE_HINT SIZE_T GetAllocatedSize() const
Definition Deque.h:219
void Reset()
Definition Deque.h:343
const ElementType & First() const
Definition Deque.h:186
UE_FORCEINLINE_HINT void PushFirst(ElementType &&Element)
Definition Deque.h:275
UE_FORCEINLINE_HINT SizeType Num() const
Definition Deque.h:208
TDeque(std::initializer_list< ElementType > InList)
Definition Deque.h:122
TDeque(const TDeque &Other)
Definition Deque.h:116
void PopLast()
Definition Deque.h:284
UE_FORCEINLINE_HINT IteratorType end()
Definition Deque.h:399
const ElementType & Last() const
Definition Deque.h:174
ElementType & EmplaceLast(ArgsType &&... Args)
Definition Deque.h:229
UE_FORCEINLINE_HINT bool IsEmpty() const
Definition Deque.h:198
const ElementType & operator[](SizeType Index) const
Definition Deque.h:162
TDeque(TDeque &&Other)
Definition Deque.h:111
UE_FORCEINLINE_HINT void PushLast(ElementType &&Element)
Definition Deque.h:262
~TDeque()
Definition Deque.h:128
UE_FORCEINLINE_HINT void PushFirst(const ElementType &Element)
Definition Deque.h:270
TDeque & operator=(TDeque &&Other)
Definition Deque.h:135
UE_FORCEINLINE_HINT ConstIteratorType begin() const
Definition Deque.h:387
bool operator!=(const TDeque &Right) const
Definition Deque.h:612
UE::Deque::Private::TIterator< ElementType, SizeType > IteratorType
Definition Deque.h:105
ElementType & operator[](SizeType Index)
Definition Deque.h:168
UE_FORCEINLINE_HINT ConstIteratorType end() const
Definition Deque.h:395
bool operator==(const TDeque &Right) const
Definition Deque.h:592
typename InAllocatorType::SizeType SizeType
Definition Deque.h:96
Definition IteratorAdapter.h:30
void Increment()
Definition Deque.h:60
InSizeType SizeType
Definition Deque.h:42
UE_FORCEINLINE_HINT ElementType & Dereference() const
Definition Deque.h:55
TIteratorBase(ElementType *Data, SizeType Range, SizeType Offset)
Definition Deque.h:50
UE_FORCEINLINE_HINT bool Equals(const TIteratorBase &Other) const
Definition Deque.h:66
InElementType ElementType
Definition Deque.h:41
@ Count
Definition AudioMixerDevice.h:90
Definition OverriddenPropertySet.cpp:45
UE_FORCEINLINE_HINT InSizeType WrapAround(InSizeType Index, InSizeType Range)
Definition Deque.h:29
Definition AdvancedWidgetsModule.cpp:13
U16 Index
Definition radfft.cpp:71