rvalue reference support for heap functions and etl::priority_queue

This commit is contained in:
John Wellbelove 2020-03-18 19:49:55 +00:00
parent 7b48e3ebf3
commit 582aa051c5
9 changed files with 254 additions and 27 deletions

View File

@ -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)
{

View File

@ -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
};
}

View File

@ -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)

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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());

View File

@ -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)
{