diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 15fe212e..da803135 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -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::difference_type difference_t; typedef typename etl::iterator_traits::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) { diff --git a/include/etl/priority_queue.h b/include/etl/priority_queue.h index 2803139e..d9cf6891 100644 --- a/include/etl/priority_queue.h +++ b/include/etl/priority_queue.h @@ -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::difference_type difference_type; - private: - - typedef typename etl::parameter_type::type parameter_t; - - public: - //************************************************************************* /// Gets a reference to the highest priority value in the priority queue.
/// \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::clone(rhs); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor + //************************************************************************* + priority_queue(priority_queue&& rhs) + : etl::ipriority_queue() + { + etl::ipriority_queue::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::move(etl::move(rhs)); + } + + return *this; + } +#endif }; } diff --git a/include/etl/version.h b/include/etl/version.h index 271162b7..c5609919 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -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) diff --git a/library.json b/library.json index cb497a50..f8a70e11 100644 --- a/library.json +++ b/library.json @@ -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" diff --git a/library.properties b/library.properties index bc1d9f2c..8cdb953f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=16.5.3 +version=16.6.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/support/Release notes.txt b/support/Release notes.txt index 69e794a1..2a0985fb 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -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 diff --git a/test/data.h b/test/data.h index a1756736..68cb9054 100644 --- a/test/data.h +++ b/test/data.h @@ -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(); diff --git a/test/test_algorithm.cpp b/test/test_algorithm.cpp index c985dffe..e425f430 100644 --- a/test/test_algorithm.cpp +++ b/test/test_algorithm.cpp @@ -46,12 +46,15 @@ SOFTWARE. namespace { using NDC = TestDataNDC; + using ItemM = TestDataM; std::random_device rng; std::mt19937 urng(rng()); - typedef std::vector Vector; + using Vector = std::vector; Vector data = { 2, 1, 4, 3, 6, 5, 8, 7, 10, 9 }; + using VectorM = std::vector; + 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 dataSL = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - typedef std::list List; + using List = std::list; 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 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()); diff --git a/test/test_priority_queue.cpp b/test/test_priority_queue.cpp index 36ab6168..baaef13a 100644 --- a/test/test_priority_queue.cpp +++ b/test/test_priority_queue.cpp @@ -32,9 +32,14 @@ SOFTWARE. #include "etl/priority_queue.h" #include +#include + +#include "data.h" namespace { + using ItemM = TestDataM; + 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 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 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 priority_queue; + std::priority_queue 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 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 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) {