Skip to content

Commit 0a008bd

Browse files
committed
priority_queue: support storing non-copyable types in collection
Previously compilation error was generated while trying to add non-copyable item into collection.
1 parent 7fadbf0 commit 0a008bd

File tree

2 files changed

+119
-12
lines changed

2 files changed

+119
-12
lines changed

include/EASTL/heap.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,11 @@ namespace eastl
322322
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
323323
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
324324

325-
const value_type tempBottom(*(last - 1));
325+
value_type tempBottom(eastl::forward<value_type>(*(last - 1)));
326326

327-
eastl::promote_heap<RandomAccessIterator, difference_type, value_type, Compare>
328-
(first, (difference_type)0, (difference_type)(last - first - 1), tempBottom, compare);
327+
eastl::promote_heap<RandomAccessIterator, difference_type, value_type, Compare>(
328+
first, (difference_type)0, (difference_type)(last - first - 1), eastl::forward<value_type>(tempBottom),
329+
compare);
329330
}
330331

331332

@@ -505,8 +506,9 @@ namespace eastl
505506

506507
const value_type tempBottom(*(first + heapSize - 1));
507508
*(first + heapSize - 1) = *(first + position);
508-
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type>
509-
(first, (difference_type)0, (difference_type)(heapSize - 1), (difference_type)position, tempBottom);
509+
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type>(
510+
first, (difference_type)0, (difference_type)(heapSize - 1), (difference_type)position,
511+
eastl::forward<const value_type>(tempBottom));
510512
}
511513

512514

@@ -526,10 +528,11 @@ namespace eastl
526528
typedef typename eastl::iterator_traits<RandomAccessIterator>::difference_type difference_type;
527529
typedef typename eastl::iterator_traits<RandomAccessIterator>::value_type value_type;
528530

529-
const value_type tempBottom(*(first + heapSize - 1));
531+
value_type tempBottom(*(first + heapSize - 1));
530532
*(first + heapSize - 1) = *(first + position);
531-
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type, Compare>
532-
(first, (difference_type)0, (difference_type)(heapSize - 1), (difference_type)position, tempBottom, compare);
533+
eastl::adjust_heap<RandomAccessIterator, difference_type, value_type, Compare>(
534+
first, (difference_type)0, (difference_type)(heapSize - 1), (difference_type)position,
535+
eastl::forward<const value_type>(tempBottom), compare);
533536
}
534537

535538

@@ -554,8 +557,8 @@ namespace eastl
554557

555558
value_type tempBottom(*(first + heapSize - 1));
556559

557-
eastl::promote_heap<RandomAccessIterator, difference_type, value_type>
558-
(first, (difference_type)0, (difference_type)(heapSize - 1), tempBottom);
560+
eastl::promote_heap<RandomAccessIterator, difference_type, value_type>(
561+
first, (difference_type)0, (difference_type)(heapSize - 1), eastl::forward<const value_type>(tempBottom));
559562
}
560563

561564

@@ -574,8 +577,9 @@ namespace eastl
574577

575578
value_type tempBottom(*(first + heapSize - 1));
576579

577-
eastl::promote_heap<RandomAccessIterator, difference_type, value_type, Compare>
578-
(first, (difference_type)0, (difference_type)(heapSize - 1), tempBottom, compare);
580+
eastl::promote_heap<RandomAccessIterator, difference_type, value_type, Compare>(
581+
first, (difference_type)0, (difference_type)(heapSize - 1), eastl::forward<const value_type>(tempBottom),
582+
compare);
579583
}
580584

581585

test/source/TestExtra.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ namespace eastl
6868
#include <EASTL/hash_set.h>
6969
#include <EASTL/random.h>
7070
#include <EASTL/bit.h>
71+
#include <EASTL/unique_ptr.h>
7172
#include <EASTL/core_allocator_adapter.h>
7273
#include <EASTL/bonus/call_traits.h>
7374
#include <EASTL/bonus/compressed_pair.h>
@@ -681,6 +682,107 @@ static int TestPriorityQueue()
681682

682683

683684

685+
///////////////////////////////////////////////////////////////////////////////
686+
// TestPriorityQueueNonCopyable
687+
// Test compilation of move-only type with priority_queue with custom comparator
688+
//
689+
690+
691+
class NonCopyableString : public eastl::string
692+
{
693+
public:
694+
using Base = eastl::string;
695+
696+
using Base::Base;
697+
EA_NON_COPYABLE(NonCopyableString);
698+
NonCopyableString(NonCopyableString&&) = default;
699+
NonCopyableString& operator=(NonCopyableString&&) = default;
700+
};
701+
702+
703+
static void TestPriorityQueueNonCopyable_DefaultComparator(int& nErrorCount)
704+
{
705+
using Queue = eastl::priority_queue<NonCopyableString, vector<NonCopyableString>>;
706+
707+
Queue queue;
708+
queue.push("A");
709+
queue.emplace("");
710+
queue.push("Mem");
711+
queue.emplace("Hello World");
712+
713+
EATEST_VERIFY(!queue.empty());
714+
EATEST_VERIFY(queue.size() == 4);
715+
716+
EATEST_VERIFY(queue.top() == "Mem");
717+
718+
queue.pop();
719+
EATEST_VERIFY(queue.top() == "Hello World");
720+
721+
queue.pop();
722+
EATEST_VERIFY(queue.top() == "A");
723+
724+
queue.pop();
725+
EATEST_VERIFY(queue.top() == "");
726+
727+
queue.pop();
728+
EATEST_VERIFY(queue.empty());
729+
}
730+
731+
732+
template <typename T = void>
733+
struct unique_ptr_less
734+
{
735+
bool operator()(const unique_ptr<T>& a, const unique_ptr<T>& b) const { return *a < *b; }
736+
};
737+
738+
739+
static void TestPriorityQueueNonCopyable_CustomComparator(int& nErrorCount)
740+
{
741+
using Value = unique_ptr<int>;
742+
using Queue = eastl::priority_queue<Value, vector<Value>, unique_ptr_less<int>>;
743+
744+
Queue queue;
745+
746+
queue.push(eastl::make_unique<int>(5));
747+
queue.emplace(eastl::make_unique<int>(1));
748+
queue.push(eastl::make_unique<int>(15));
749+
queue.emplace(eastl::make_unique<int>(7));
750+
751+
EATEST_VERIFY(!queue.empty());
752+
EATEST_VERIFY(queue.size() == 4);
753+
754+
EATEST_VERIFY(queue.top() && *queue.top() == 15);
755+
756+
queue.pop();
757+
EATEST_VERIFY(queue.top() && *queue.top() == 7);
758+
759+
queue.pop();
760+
EATEST_VERIFY(queue.top() && *queue.top() == 5);
761+
762+
queue.pop();
763+
EATEST_VERIFY(queue.top() && *queue.top() == 1);
764+
765+
queue.pop();
766+
EATEST_VERIFY(queue.empty());
767+
}
768+
769+
770+
static int TestPriorityQueueNonCopyable()
771+
{
772+
int nErrorCount = 0;
773+
774+
TestObject::Reset();
775+
776+
TestPriorityQueueNonCopyable_DefaultComparator(nErrorCount);
777+
778+
TestPriorityQueueNonCopyable_CustomComparator(nErrorCount);
779+
780+
return nErrorCount;
781+
}
782+
783+
784+
785+
684786
// Template instantations.
685787
// These tell the compiler to compile all the functions for the given class.
686788
template class eastl::stack<int, vector<int> >;
@@ -1400,6 +1502,7 @@ int TestExtra()
14001502
nErrorCount += TestForwardDeclarations();
14011503
nErrorCount += TestQueue();
14021504
nErrorCount += TestPriorityQueue();
1505+
nErrorCount += TestPriorityQueueNonCopyable();
14031506
nErrorCount += TestStack();
14041507
nErrorCount += TestCompressedPair();
14051508
nErrorCount += TestCallTraits();

0 commit comments

Comments
 (0)