mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
rvalue reference support for heap functions and etl::priority_queue
This commit is contained in:
parent
7b48e3ebf3
commit
582aa051c5
@ -942,12 +942,12 @@ namespace etl
|
||||
|
||||
while ((value_index > top_index) && compare(first[parent], value))
|
||||
{
|
||||
first[value_index] = first[parent];
|
||||
first[value_index] = etl::move(first[parent]);
|
||||
value_index = parent;
|
||||
parent = (value_index - 1) / 2;
|
||||
}
|
||||
|
||||
first[value_index] = value;
|
||||
first[value_index] = etl::move(value);
|
||||
}
|
||||
|
||||
// Adjust Heap Helper
|
||||
@ -964,18 +964,18 @@ namespace etl
|
||||
--child2nd;
|
||||
}
|
||||
|
||||
first[value_index] = first[child2nd];
|
||||
first[value_index] = etl::move(first[child2nd]);
|
||||
value_index = child2nd;
|
||||
child2nd = 2 * (child2nd + 1);
|
||||
}
|
||||
|
||||
if (child2nd == length)
|
||||
{
|
||||
first[value_index] = first[child2nd - 1];
|
||||
first[value_index] = etl::move(first[child2nd - 1]);
|
||||
value_index = child2nd - 1;
|
||||
}
|
||||
|
||||
push_heap(first, value_index, top_index, value, compare);
|
||||
push_heap(first, value_index, top_index, etl::move(value), compare);
|
||||
}
|
||||
|
||||
// Is Heap Helper
|
||||
@ -1011,7 +1011,7 @@ namespace etl
|
||||
value_t value = etl::move(last[-1]);
|
||||
last[-1] = etl::move(first[0]);
|
||||
|
||||
private_heap::adjust_heap(first, distance_t(0), distance_t(last - first - 1), value, compare);
|
||||
private_heap::adjust_heap(first, distance_t(0), distance_t(last - first - 1), etl::move(value), compare);
|
||||
}
|
||||
|
||||
// Pop Heap
|
||||
@ -1030,7 +1030,7 @@ namespace etl
|
||||
typedef typename etl::iterator_traits<TIterator>::difference_type difference_t;
|
||||
typedef typename etl::iterator_traits<TIterator>::value_type value_t;
|
||||
|
||||
private_heap::push_heap(first, difference_t(last - first - 1), difference_t(0), value_t(*(last - 1)), compare);
|
||||
private_heap::push_heap(first, difference_t(last - first - 1), difference_t(0), value_t(etl::move(*(last - 1))), compare);
|
||||
}
|
||||
|
||||
// Push Heap
|
||||
@ -1058,7 +1058,7 @@ namespace etl
|
||||
|
||||
while (true)
|
||||
{
|
||||
private_heap::adjust_heap(first, parent, length, *(first + parent), compare);
|
||||
private_heap::adjust_heap(first, parent, length, etl::move(*(first + parent)), compare);
|
||||
|
||||
if (parent == 0)
|
||||
{
|
||||
|
||||
@ -125,15 +125,12 @@ namespace etl
|
||||
typedef TCompare compare_type; ///< The comparison type.
|
||||
typedef T& reference; ///< A reference to the type used in the queue.
|
||||
typedef const T& const_reference; ///< A const reference to the type used in the queue.
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
typedef T&& rvalue_reference; ///< An rvalue reference to the type used in the queue.
|
||||
#endif
|
||||
typedef typename TContainer::size_type size_type; ///< The type used for determining the size of the queue.
|
||||
typedef typename etl::iterator_traits<typename TContainer::iterator>::difference_type difference_type;
|
||||
|
||||
private:
|
||||
|
||||
typedef typename etl::parameter_type<T>::type parameter_t;
|
||||
|
||||
public:
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets a reference to the highest priority value in the priority queue.<br>
|
||||
/// \return A reference to the highest priority value in the priority queue.
|
||||
@ -158,7 +155,7 @@ namespace etl
|
||||
/// is the priority queue is already full.
|
||||
///\param value The value to push to the queue.
|
||||
//*************************************************************************
|
||||
void push(parameter_t value)
|
||||
void push(const_reference value)
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(etl::priority_queue_full));
|
||||
|
||||
@ -168,6 +165,24 @@ namespace etl
|
||||
etl::push_heap(container.begin(), container.end(), compare);
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Moves a value to the queue.
|
||||
/// If asserts or exceptions are enabled, throws an etl::priority_queue_full
|
||||
/// is the priority queue is already full.
|
||||
///\param value The value to push to the queue.
|
||||
//*************************************************************************
|
||||
void push(rvalue_reference value)
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(etl::priority_queue_full));
|
||||
|
||||
// Put element at end
|
||||
container.push_back(etl::move(value));
|
||||
// Make elements in container into heap
|
||||
etl::push_heap(container.begin(), container.end(), compare);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_PRIORITY_QUEUE_FORCE_CPP03)
|
||||
//*************************************************************************
|
||||
/// Emplaces a value to the queue.
|
||||
@ -361,6 +376,20 @@ namespace etl
|
||||
assign(other.container.cbegin(), other.container.cend());
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Make this a moved version of the supplied priority queue
|
||||
//*************************************************************************
|
||||
void move(ipriority_queue&& other)
|
||||
{
|
||||
while (!other.empty())
|
||||
{
|
||||
push(etl::move(other.top()));
|
||||
other.pop();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// The constructor that is called from derived classes.
|
||||
//*************************************************************************
|
||||
@ -412,6 +441,17 @@ namespace etl
|
||||
etl::ipriority_queue<T, TContainer, TCompare>::clone(rhs);
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Move constructor
|
||||
//*************************************************************************
|
||||
priority_queue(priority_queue&& rhs)
|
||||
: etl::ipriority_queue<T, TContainer, TCompare>()
|
||||
{
|
||||
etl::ipriority_queue<T, TContainer, TCompare>::move(etl::move(rhs));
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor, from an iterator range.
|
||||
///\tparam TIterator The iterator type.
|
||||
@ -445,6 +485,21 @@ namespace etl
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Move assignment operator.
|
||||
//*************************************************************************
|
||||
priority_queue& operator = (priority_queue&& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
etl::ipriority_queue<T, TContainer, TCompare>::move(etl::move(rhs));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -38,8 +38,8 @@ SOFTWARE.
|
||||
///\ingroup utilities
|
||||
|
||||
#define ETL_VERSION_MAJOR 16
|
||||
#define ETL_VERSION_MINOR 5
|
||||
#define ETL_VERSION_PATCH 3
|
||||
#define ETL_VERSION_MINOR 6
|
||||
#define ETL_VERSION_PATCH 0
|
||||
#define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) "." ETL_STRINGIFY(ETL_VERSION_MINOR) "." ETL_STRINGIFY(ETL_VERSION_PATCH)
|
||||
#define ETL_VERSION_W ETL_STRINGIFY(ETL_VERSION_MAJOR) L"." ETL_STRINGIFY(ETL_VERSION_MINOR) L"." ETL_STRINGIFY(ETL_VERSION_PATCH)
|
||||
#define ETL_VERSION_U16 ETL_STRINGIFY(ETL_VERSION_MAJOR) u"." ETL_STRINGIFY(ETL_VERSION_MINOR) u"." ETL_STRINGIFY(ETL_VERSION_PATCH)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Embedded Template Library",
|
||||
"version": "16.5.3",
|
||||
"version": "16.6.0",
|
||||
"authors": {
|
||||
"name": "John Wellbelove",
|
||||
"email": "john.wellbelove@etlcpp.com"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
name=Embedded Template Library
|
||||
version=16.5.3
|
||||
version=16.6.0
|
||||
author= John Wellbelove <john.wellbelove@etlcpp.com>
|
||||
maintainer=John Wellbelove <john.wellbelove@etlcpp.com>
|
||||
license=MIT
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
===============================================================================
|
||||
16.6.0
|
||||
rvalue reference support for heap functions and etl::priority_queue
|
||||
|
||||
===============================================================================
|
||||
16.5.3
|
||||
type_traits.h is_one_of fix for C++03
|
||||
|
||||
@ -189,7 +189,7 @@ public:
|
||||
: value(other.value)
|
||||
, valid(true)
|
||||
{
|
||||
other.value = T();
|
||||
other.value = std::move(T());
|
||||
other.valid = false;
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ public:
|
||||
|
||||
TestDataM& operator =(TestDataM&& other)
|
||||
{
|
||||
value = other.value;
|
||||
value = std::move(other.value);
|
||||
valid = true;
|
||||
|
||||
other.value = T();
|
||||
|
||||
@ -46,12 +46,15 @@ SOFTWARE.
|
||||
namespace
|
||||
{
|
||||
using NDC = TestDataNDC<int>;
|
||||
using ItemM = TestDataM<std::string>;
|
||||
std::random_device rng;
|
||||
std::mt19937 urng(rng());
|
||||
|
||||
typedef std::vector<int> Vector;
|
||||
using Vector = std::vector<int>;
|
||||
Vector data = { 2, 1, 4, 3, 6, 5, 8, 7, 10, 9 };
|
||||
|
||||
using VectorM = std::vector<ItemM>;
|
||||
|
||||
constexpr size_t SIZE = 10;
|
||||
|
||||
int dataA[SIZE] = { 2, 1, 4, 3, 6, 5, 8, 7, 10, 9 };
|
||||
@ -59,7 +62,7 @@ namespace
|
||||
int dataS[SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
std::list<int> dataSL = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
|
||||
typedef std::list<int> List;
|
||||
using List = std::list<int>;
|
||||
List dataL = { 2, 1, 4, 3, 6, 5, 8, 7, 10, 9 };
|
||||
|
||||
int dataEQ[SIZE] = { 1, 1, 3, 3, 5, 5, 7, 7, 9, 9 };
|
||||
@ -753,8 +756,12 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST(heap)
|
||||
{
|
||||
Vector data1 = dataV;
|
||||
Vector data2 = dataV;
|
||||
using Vector = std::vector<std::string>;
|
||||
|
||||
std::string a("A"), b("B"), c("C"), d("D"), e("E"), f("F"), g("G"), h("H"), i("I"), j("J");
|
||||
|
||||
Vector data1 = { a, b, c, d, e, f, g, h, i, j };
|
||||
Vector data2 = { a, b, c, d, e, f, g, h, i, j };
|
||||
|
||||
std::make_heap(data1.begin(), data1.end());
|
||||
etl::make_heap(data2.begin(), data2.end());
|
||||
@ -775,6 +782,79 @@ namespace
|
||||
CHECK(std::is_heap(data1.begin(), data1.end()));
|
||||
CHECK(std::is_heap(data2.begin(), data2.end()));
|
||||
|
||||
CHECK_EQUAL(data1.size(), data2.size());
|
||||
|
||||
isEqual = std::equal(std::begin(data1), std::end(data1), std::begin(data2));
|
||||
CHECK(isEqual);
|
||||
|
||||
CHECK(std::is_heap(data2.begin(), data2.end()));
|
||||
|
||||
isEqual = std::equal(std::begin(data1), std::end(data1), std::begin(data2));
|
||||
CHECK(isEqual);
|
||||
|
||||
data1.push_back(std::string("K"));
|
||||
data2.push_back(std::string("K"));
|
||||
|
||||
std::push_heap(data1.begin(), data1.end());
|
||||
etl::push_heap(data2.begin(), data2.end());
|
||||
|
||||
CHECK(std::is_heap(data2.begin(), data2.end()));
|
||||
|
||||
isEqual = std::equal(std::begin(data1), std::end(data1), std::begin(data2));
|
||||
CHECK(isEqual);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(heap_movable)
|
||||
{
|
||||
ItemM a("A"), b("B"), c("C"), d("D"), e("E"), f("F"), g("G"), h("H"), i("I"), j("J");
|
||||
|
||||
VectorM data1;
|
||||
data1.emplace_back(std::move(b));
|
||||
data1.emplace_back(std::move(a));
|
||||
data1.emplace_back(std::move(d));
|
||||
data1.emplace_back(std::move(c));
|
||||
data1.emplace_back(std::move(f));
|
||||
data1.emplace_back(std::move(e));
|
||||
data1.emplace_back(std::move(h));
|
||||
data1.emplace_back(std::move(g));
|
||||
data1.emplace_back(std::move(j));
|
||||
data1.emplace_back(std::move(i));
|
||||
|
||||
VectorM data2;
|
||||
data2.emplace_back(ItemM("B"));
|
||||
data2.emplace_back(ItemM("A"));
|
||||
data2.emplace_back(ItemM("D"));
|
||||
data2.emplace_back(ItemM("C"));
|
||||
data2.emplace_back(ItemM("F"));
|
||||
data2.emplace_back(ItemM("E"));
|
||||
data2.emplace_back(ItemM("H"));
|
||||
data2.emplace_back(ItemM("G"));
|
||||
data2.emplace_back(ItemM("J"));
|
||||
data2.emplace_back(ItemM("I"));
|
||||
|
||||
std::make_heap(data1.begin(), data1.end());
|
||||
etl::make_heap(data2.begin(), data2.end());
|
||||
|
||||
bool isEqual;
|
||||
|
||||
CHECK(std::is_heap(data1.begin(), data1.end()));
|
||||
CHECK(std::is_heap(data2.begin(), data2.end()));
|
||||
|
||||
CHECK_EQUAL(data1.size(), data2.size());
|
||||
|
||||
isEqual = std::equal(std::begin(data1), std::end(data1), std::begin(data2));
|
||||
CHECK(isEqual);
|
||||
|
||||
std::pop_heap(data1.begin(), data1.end());
|
||||
etl::pop_heap(data2.begin(), data2.end());
|
||||
|
||||
data1.pop_back();
|
||||
data2.pop_back();
|
||||
|
||||
CHECK(std::is_heap(data1.begin(), data1.end()));
|
||||
CHECK(std::is_heap(data2.begin(), data2.end()));
|
||||
|
||||
isEqual = std::equal(std::begin(data1), std::end(data1), std::begin(data2));
|
||||
CHECK(isEqual);
|
||||
|
||||
@ -783,8 +863,8 @@ namespace
|
||||
isEqual = std::equal(std::begin(data1), std::end(data1), std::begin(data2));
|
||||
CHECK(isEqual);
|
||||
|
||||
data1.push_back(5);
|
||||
data2.push_back(5);
|
||||
data1.push_back(ItemM("K"));
|
||||
data2.push_back(ItemM("K"));
|
||||
|
||||
std::push_heap(data1.begin(), data1.end());
|
||||
etl::push_heap(data2.begin(), data2.end());
|
||||
|
||||
@ -32,9 +32,14 @@ SOFTWARE.
|
||||
|
||||
#include "etl/priority_queue.h"
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "data.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
using ItemM = TestDataM<std::string>;
|
||||
|
||||
struct Item
|
||||
{
|
||||
Item(char c_, int i_, double d_)
|
||||
@ -118,6 +123,32 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_constructor)
|
||||
{
|
||||
ItemM a("A"), b("B"), c("C"), d("D");
|
||||
|
||||
etl::priority_queue<ItemM, SIZE> priority_queue;
|
||||
|
||||
priority_queue.push(std::move(c));
|
||||
priority_queue.push(std::move(d));
|
||||
priority_queue.push(std::move(a));
|
||||
priority_queue.push(std::move(b));
|
||||
|
||||
etl::priority_queue<ItemM, SIZE> priority_queue2(std::move(priority_queue));
|
||||
|
||||
CHECK_EQUAL(0U, priority_queue.size());
|
||||
CHECK_EQUAL(SIZE, priority_queue2.size());
|
||||
|
||||
CHECK_EQUAL(priority_queue2.top().value, "D");
|
||||
priority_queue2.pop();
|
||||
CHECK_EQUAL(priority_queue2.top().value, "C");
|
||||
priority_queue2.pop();
|
||||
CHECK_EQUAL(priority_queue2.top().value, "B");
|
||||
priority_queue2.pop();
|
||||
CHECK_EQUAL(priority_queue2.top().value, "A");
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_constructor_range)
|
||||
{
|
||||
@ -281,6 +312,35 @@ namespace
|
||||
CHECK_EQUAL(compare_priority_queue.top(), priority_queue.top());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_push_movable)
|
||||
{
|
||||
ItemM a("A"), b("B"), c("C"), d("D");
|
||||
|
||||
etl::priority_queue<ItemM, SIZE> priority_queue;
|
||||
std::priority_queue<ItemM> compare_priority_queue;
|
||||
|
||||
priority_queue.push(std::move(c));
|
||||
priority_queue.push(std::move(d));
|
||||
priority_queue.push(std::move(a));
|
||||
priority_queue.push(std::move(b));
|
||||
|
||||
compare_priority_queue.push(ItemM("C"));
|
||||
compare_priority_queue.push(ItemM("D"));
|
||||
compare_priority_queue.push(ItemM("A"));
|
||||
compare_priority_queue.push(ItemM("B"));
|
||||
|
||||
CHECK_EQUAL(compare_priority_queue.size(), priority_queue.size());
|
||||
CHECK(!priority_queue.empty());
|
||||
|
||||
while (!priority_queue.empty())
|
||||
{
|
||||
CHECK_EQUAL(compare_priority_queue.top(), priority_queue.top());
|
||||
compare_priority_queue.pop();
|
||||
priority_queue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_emplace)
|
||||
{
|
||||
@ -444,6 +504,34 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_assignment)
|
||||
{
|
||||
ItemM a("A"), b("B"), c("C"), d("D");
|
||||
|
||||
etl::priority_queue<ItemM, SIZE> priority_queue;
|
||||
|
||||
priority_queue.push(std::move(c));
|
||||
priority_queue.push(std::move(d));
|
||||
priority_queue.push(std::move(a));
|
||||
priority_queue.push(std::move(b));
|
||||
|
||||
etl::priority_queue<ItemM, SIZE> priority_queue2;
|
||||
|
||||
priority_queue2 = std::move(priority_queue);
|
||||
|
||||
CHECK_EQUAL(0U, priority_queue.size());
|
||||
CHECK_EQUAL(SIZE, priority_queue2.size());
|
||||
|
||||
CHECK_EQUAL(priority_queue2.top().value, "D");
|
||||
priority_queue2.pop();
|
||||
CHECK_EQUAL(priority_queue2.top().value, "C");
|
||||
priority_queue2.pop();
|
||||
CHECK_EQUAL(priority_queue2.top().value, "B");
|
||||
priority_queue2.pop();
|
||||
CHECK_EQUAL(priority_queue2.top().value, "A");
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assignment_interface)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user