From a8f07e0622f1e908a5ca3908f8b5bcc68db61080 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 29 Dec 2018 15:34:53 +0000 Subject: [PATCH 01/14] Added rvalue reference variants --- include/etl/memory.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/include/etl/memory.h b/include/etl/memory.h index 0be98a1b..0f6df281 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -417,6 +417,16 @@ namespace etl ::new (p) T(value); } + //***************************************************************************** + /// Copy construct an item at address p. + ///\ingroup memory + //***************************************************************************** + template + void create_copy_at(T* p, T&& value) + { + ::new (p) T(std::move(value)); + } + //***************************************************************************** /// Copy construct an item at address p. ///\ingroup memory @@ -462,6 +472,17 @@ namespace etl return *reinterpret_cast(p); } + //***************************************************************************** + /// Construct an item at address p. + ///\ingroup memory + //***************************************************************************** + template + T& make_copy_at(T* p, T&& other) + { + ::new (p) T(std::move(other)); + return *reinterpret_cast(p); + } + //***************************************************************************** /// Construct an item at address p. ///\ingroup memory @@ -485,6 +506,17 @@ namespace etl return *reinterpret_cast(p); } + //***************************************************************************** + /// Construct an item at address p. + ///\ingroup memory + //***************************************************************************** + template + T& make_value_at(T* p, TParameter&& value) + { + ::new (p) T(std::move(value)); + return *reinterpret_cast(p); + } + //***************************************************************************** /// Construct an item at address p. ///\ingroup memory From fa891b9dbcec839cd764d7583f98ebda761f6389 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 29 Dec 2018 15:35:12 +0000 Subject: [PATCH 02/14] Minor change top variable declaration --- test/test_deque.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_deque.cpp b/test/test_deque.cpp index bd57e81f..5e3ab4a5 100644 --- a/test/test_deque.cpp +++ b/test/test_deque.cpp @@ -1693,7 +1693,7 @@ namespace TEST(test_move) { const size_t SIZE = 10U; - typedef etl::deque, SIZE> Data; + typedef etl::deque, SIZE> Data; Data data1; From 9266920e2ac571e88ff0440712c44773445bb6ea Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 29 Dec 2018 15:36:08 +0000 Subject: [PATCH 03/14] Added rvalue reference push_back & insert. --- include/etl/vector.h | 95 ++++++++++++++++++++++++-------- test/test_vector.cpp | 25 +++++++++ test/test_vector_non_trivial.cpp | 75 +++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 22 deletions(-) diff --git a/include/etl/vector.h b/include/etl/vector.h index 724712e8..fd5cc855 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -405,7 +405,7 @@ namespace etl /// If asserts or exceptions are enabled, emits vector_full if the vector is already full. ///\param value The value to add. //********************************************************************* - void push_back(parameter_t value) + void push_back(const T& value) { #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(size() != CAPACITY, ETL_ERROR(vector_full)); @@ -413,6 +413,19 @@ namespace etl create_back(value); } + //********************************************************************* + /// Inserts a value at the end of the vector. + /// If asserts or exceptions are enabled, emits vector_full if the vector is already full. + ///\param value The value to add. + //********************************************************************* + void push_back(T&& value) + { +#if defined(ETL_CHECK_PUSH_POP) + ETL_ASSERT(size() != CAPACITY, ETL_ERROR(vector_full)); +#endif + create_back(std::move(value)); + } + #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) && !ETL_VECTOR_FORCE_CPP03 //********************************************************************* /// Constructs a value at the end of the vector. @@ -513,7 +526,7 @@ namespace etl ///\param position The position to insert before. ///\param value The value to insert. //********************************************************************* - iterator insert(iterator position, parameter_t value) + iterator insert(iterator position, const T& value) { ETL_ASSERT(size() + 1 <= CAPACITY, ETL_ERROR(vector_full)); @@ -524,13 +537,37 @@ namespace etl else { create_back(back()); - std::copy_backward(position, p_end - 1, p_end); + std::copy_backward(position, p_end - 2, p_end - 1); *position = value; } return position; } + //********************************************************************* + /// Inserts a value to the vector. + /// If asserts or exceptions are enabled, emits vector_full if the vector is already full. + ///\param position The position to insert before. + ///\param value The value to insert. + //********************************************************************* + iterator insert(iterator position, T&& value) + { + ETL_ASSERT(size() + 1 <= CAPACITY, ETL_ERROR(vector_full)); + + if (position == end()) + { + create_back(std::move(value)); + } + else + { + create_back(std::move(back())); + std::move_backward(position, p_end - 2, p_end - 1); + *position = std::move(value); + } + + return position; + } + //************************************************************************* /// Emplaces a value to the vextor at the specified position. //************************************************************************* @@ -551,7 +588,7 @@ namespace etl { p = etl::addressof(*position); create_back(back()); - std::copy_backward(position, p_end - 1, p_end); + std::copy_backward(position, p_end - 2, p_end - 1); (*position).~T(); } @@ -576,7 +613,7 @@ namespace etl { p = etl::addressof(*position); create_back(back()); - std::copy_backward(position, p_end - 1, p_end); + std::copy_backward(position, p_end - 2, p_end - 1); (*position).~T(); } @@ -601,7 +638,7 @@ namespace etl { p = etl::addressof(*position); create_back(back()); - std::copy_backward(position, p_end - 1, p_end); + std::copy_backward(position, p_end - 2, p_end - 1); (*position).~T(); } @@ -626,7 +663,7 @@ namespace etl { p = etl::addressof(*position); create_back(back()); - std::copy_backward(position, p_end - 1, p_end); + std::copy_backward(position, p_end - 2, p_end - 1); (*position).~T(); } @@ -651,7 +688,7 @@ namespace etl { p = etl::addressof(*position); create_back(back()); - std::copy_backward(position, p_end - 1, p_end); + std::copy_backward(position, p_end - 2, p_end - 1); (*position).~T(); } @@ -701,15 +738,15 @@ namespace etl etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old); ETL_ADD_DEBUG_COUNT(construct_old_n) - // Copy old. - etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end); + // Copy old. + etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end); // Construct new. etl::uninitialized_fill_n(p_end, construct_new_n, value); ETL_ADD_DEBUG_COUNT(construct_new_n) - // Copy new. - std::fill_n(p_buffer + insert_begin, copy_new_n, value); + // Copy new. + std::fill_n(p_buffer + insert_begin, copy_new_n, value); p_end += n; } @@ -758,15 +795,15 @@ namespace etl etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old); ETL_ADD_DEBUG_COUNT(construct_old_n) - // Copy old. - etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end); + // Copy old. + etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end); // Construct new. etl::uninitialized_copy_n(first + copy_new_n, construct_new_n, p_end); ETL_ADD_DEBUG_COUNT(construct_new_n) - // Copy new. - etl::copy_n(first, copy_new_n, p_buffer + insert_begin); + // Copy new. + etl::copy_n(first, copy_new_n, p_buffer + insert_begin); p_end += count; } @@ -806,7 +843,7 @@ namespace etl // Destroy the elements left over at the end. etl::destroy(p_end - n_delete, p_end); ETL_SUBTRACT_DEBUG_COUNT(n_delete) - p_end -= n_delete; + p_end -= n_delete; } return first; @@ -888,7 +925,7 @@ namespace etl etl::destroy(p_buffer, p_end); ETL_SUBTRACT_DEBUG_COUNT(int32_t(std::distance(p_buffer, p_end))) - p_end = p_buffer; + p_end = p_buffer; } //************************************************************************* @@ -898,7 +935,7 @@ namespace etl { uintptr_t length = p_end - p_buffer; p_buffer = p_buffer_; - p_end = p_buffer_ + length; + p_end = p_buffer_ + length; } private: @@ -920,7 +957,7 @@ namespace etl //********************************************************************* /// Create a new element with a value at the back //********************************************************************* - inline void create_back(parameter_t value) + inline void create_back(const T& value) { etl::create_copy_at(p_end, value); ETL_INCREMENT_DEBUG_COUNT @@ -928,6 +965,17 @@ namespace etl ++p_end; } + //********************************************************************* + /// Create a new element with a value at the back + //********************************************************************* + inline void create_back(T&& value) + { + etl::create_copy_at(p_end, std::move(value)); + ETL_INCREMENT_DEBUG_COUNT + + ++p_end; + } + //********************************************************************* /// Destroy an element at the back. //********************************************************************* @@ -1035,7 +1083,12 @@ namespace etl { return !(lhs < rhs); } +} +#include "private/ivectorpointer.h" + +namespace etl +{ //*************************************************************************** /// A vector implementation that uses a fixed size buffer. ///\tparam T The element type. @@ -1260,8 +1313,6 @@ namespace etl }; } -#include "private/ivectorpointer.h" - #ifdef ETL_COMPILER_GCC #pragma GCC diagnostic pop #endif diff --git a/test/test_vector.cpp b/test/test_vector.cpp index 3b35ceac..d87f83de 100644 --- a/test/test_vector.cpp +++ b/test/test_vector.cpp @@ -514,6 +514,31 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back_literal) + { + Compare_Data compare_data; + Data data; + + compare_data.push_back(1); + compare_data.push_back(2); + compare_data.push_back(3); + compare_data.push_back(4); + + data.push_back(1); + data.push_back(2); + data.push_back(3); + data.push_back(4); + + CHECK_EQUAL(compare_data.size(), data.size()); + + bool is_equal = std::equal(data.begin(), + data.end(), + compare_data.begin()); + + CHECK(is_equal); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_push_back_excess) { diff --git a/test/test_vector_non_trivial.cpp b/test/test_vector_non_trivial.cpp index ab87b66e..a0dc480f 100644 --- a/test/test_vector_non_trivial.cpp +++ b/test/test_vector_non_trivial.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "etl/vector.h" #include "data.h" @@ -571,6 +572,80 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back_unique_ptr) + { + etl::vector, SIZE> data; + + std::unique_ptr p1(new int(1)); + std::unique_ptr p2(new int(2)); + std::unique_ptr p3(new int(3)); + std::unique_ptr p4(new int(4)); + + data.push_back(std::move(p1)); + data.push_back(std::move(p2)); + data.push_back(std::move(p3)); + data.push_back(std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + CHECK_EQUAL(1, *data[0]); + CHECK_EQUAL(2, *data[1]); + CHECK_EQUAL(3, *data[2]); + CHECK_EQUAL(4, *data[3]); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_int) + { + etl::vector data; + + int p1(1); + int p2(2); + int p3(3); + int p4(4); + + data.insert(data.begin(), p1); + data.insert(data.begin(), p2); + data.insert(data.begin(), p3); + data.insert(data.begin(), p4); + + CHECK_EQUAL(4, data[0]); + CHECK_EQUAL(3, data[1]); + CHECK_EQUAL(2, data[2]); + CHECK_EQUAL(1, data[3]); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_unique_ptr) + { + etl::vector, SIZE> data; + + std::unique_ptr p1(new int(1)); + std::unique_ptr p2(new int(2)); + std::unique_ptr p3(new int(3)); + std::unique_ptr p4(new int(4)); + + data.insert(data.begin(), std::move(p1)); + data.insert(data.begin(), std::move(p2)); + data.insert(data.begin(), std::move(p3)); + data.insert(data.begin(), std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + CHECK_EQUAL(1, *data[3]); + CHECK_EQUAL(4, *data[0]); + CHECK_EQUAL(3, *data[1]); + CHECK_EQUAL(2, *data[2]); + + } + //************************************************************************* // To test the CPP03 versions then ETL_TEST_VECTOR_CPP11 must be set to 0 in vector.h TEST_FIXTURE(SetupFixture, test_emplace_back_multiple) From 338164d871ed810ef12a8c6b31f4727a92507a02 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 29 Dec 2018 20:47:17 +0000 Subject: [PATCH 04/14] Added conditional compile directives for C++11 --- include/etl/memory.h | 4 ++++ include/etl/vector.h | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/include/etl/memory.h b/include/etl/memory.h index 0f6df281..b063dc1a 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -417,6 +417,7 @@ namespace etl ::new (p) T(value); } +#if ETL_CPP11_SUPPORTED //***************************************************************************** /// Copy construct an item at address p. ///\ingroup memory @@ -426,6 +427,7 @@ namespace etl { ::new (p) T(std::move(value)); } +#endif //***************************************************************************** /// Copy construct an item at address p. @@ -472,6 +474,7 @@ namespace etl return *reinterpret_cast(p); } +#if ETL_CPP11_SUPPORTED //***************************************************************************** /// Construct an item at address p. ///\ingroup memory @@ -482,6 +485,7 @@ namespace etl ::new (p) T(std::move(other)); return *reinterpret_cast(p); } +#endif //***************************************************************************** /// Construct an item at address p. diff --git a/include/etl/vector.h b/include/etl/vector.h index fd5cc855..99641b0e 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -413,6 +413,7 @@ namespace etl create_back(value); } +#if ETL_CPP11_SUPPORTED //********************************************************************* /// Inserts a value at the end of the vector. /// If asserts or exceptions are enabled, emits vector_full if the vector is already full. @@ -425,6 +426,7 @@ namespace etl #endif create_back(std::move(value)); } +#endif #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) && !ETL_VECTOR_FORCE_CPP03 //********************************************************************* @@ -544,6 +546,7 @@ namespace etl return position; } +#if ETL_CPP11_SUPPORTED //********************************************************************* /// Inserts a value to the vector. /// If asserts or exceptions are enabled, emits vector_full if the vector is already full. @@ -567,6 +570,7 @@ namespace etl return position; } +#endif //************************************************************************* /// Emplaces a value to the vextor at the specified position. @@ -965,6 +969,7 @@ namespace etl ++p_end; } +#if ETL_CPP11_SUPPORTED //********************************************************************* /// Create a new element with a value at the back //********************************************************************* @@ -975,6 +980,7 @@ namespace etl ++p_end; } +#endif //********************************************************************* /// Destroy an element at the back. From ca813920756900c5c39318021a87ca092cc9d5e4 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 29 Dec 2018 20:56:37 +0000 Subject: [PATCH 05/14] Added move constructor and assignment operator --- include/etl/vector.h | 49 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/include/etl/vector.h b/include/etl/vector.h index 99641b0e..8836803c 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -1289,7 +1289,10 @@ namespace etl vector(const vector& other) : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) { - this->assign(other.begin(), other.end()); + if (this != &other) + { + this->assign(other.begin(), other.end()); + } } //************************************************************************* @@ -1305,6 +1308,50 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + vector(vector&& other) + : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) + { + if (this != &other) + { + this->initialise(); + + typename etl::ivector::iterator itr = other.begin(); + while (itr != other.end()) + { + this->push_back(std::move(*itr)); + ++itr; + } + + other.initialise(); + } + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + vector& operator = (vector&& rhs) + { + if (&rhs != this) + { + this->clear(); + typename etl::ivector::iterator itr = rhs.begin(); + while (itr != rhs.end()) + { + this->push_back(std::move(*itr)); + ++itr; + } + + rhs.initialise(); + } + + return *this; + } +#endif + //************************************************************************* /// Fix the internal pointers after a low level memory copy. //************************************************************************* From 2aae4c1104b73cd2e132c82a1aa386f0fc6d1e16 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 30 Dec 2018 11:15:41 +0000 Subject: [PATCH 06/14] Added move tests --- test/test_deque.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/test/test_deque.cpp b/test/test_deque.cpp index 5e3ab4a5..5c1a21f3 100644 --- a/test/test_deque.cpp +++ b/test/test_deque.cpp @@ -156,6 +156,34 @@ namespace CHECK(std::equal(deque1.begin(), deque1.end(), deque2.begin())); } + //************************************************************************* + TEST(test_move_constructor) + { + const size_t SIZE = 10U; + typedef etl::deque, SIZE> Data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + Data deque1; + deque1.push_back(std::move(p1)); + deque1.push_back(std::move(p2)); + deque1.push_back(std::move(p3)); + deque1.push_back(std::move(p4)); + + Data deque2(std::move(deque1)); + + CHECK_EQUAL(0U, deque1.size()); + CHECK_EQUAL(4U, deque2.size()); + + CHECK_EQUAL(1U, *deque2[0]); + CHECK_EQUAL(2U, *deque2[1]); + CHECK_EQUAL(3U, *deque2[2]); + CHECK_EQUAL(4U, *deque2[3]); + } + //************************************************************************* TEST(test_assignment) { @@ -168,6 +196,35 @@ namespace CHECK(std::equal(deque1.begin(), deque1.end(), deque2.begin())); } + //************************************************************************* + TEST(test_move_assignment) + { + const size_t SIZE = 10U; + typedef etl::deque, SIZE> Data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + Data deque1; + deque1.push_back(std::move(p1)); + deque1.push_back(std::move(p2)); + deque1.push_back(std::move(p3)); + deque1.push_back(std::move(p4)); + + Data deque2; + deque2 = std::move(deque1); + + CHECK_EQUAL(0U, deque1.size()); + CHECK_EQUAL(4U, deque2.size()); + + CHECK_EQUAL(1U, *deque2[0]); + CHECK_EQUAL(2U, *deque2[1]); + CHECK_EQUAL(3U, *deque2[2]); + CHECK_EQUAL(4U, *deque2[3]); + } + //************************************************************************* TEST(test_assignment_interface) { From dc6f6796f6a92d7658e2a7072a02ae7f8d06b608 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 30 Dec 2018 11:16:33 +0000 Subject: [PATCH 07/14] Added move constructor & move assignment --- include/etl/vector.h | 104 +++++++++++++++---------------- test/test_vector_non_trivial.cpp | 57 +++++++++++++++++ 2 files changed, 109 insertions(+), 52 deletions(-) diff --git a/include/etl/vector.h b/include/etl/vector.h index 8836803c..ab975fbd 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -1173,14 +1173,6 @@ namespace etl this->assign(other.begin(), other.end()); } - //************************************************************************* - /// Destructor. - //************************************************************************* - ~vector() - { - this->clear(); - } - //************************************************************************* /// Assignment operator. //************************************************************************* @@ -1194,6 +1186,58 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + vector(vector&& other) + : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) + { + if (this != &other) + { + this->initialise(); + + typename etl::ivector::iterator itr = other.begin(); + while (itr != other.end()) + { + this->push_back(std::move(*itr)); + ++itr; + } + + other.initialise(); + } + } + + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + vector& operator = (vector&& rhs) + { + if (&rhs != this) + { + this->clear(); + typename etl::ivector::iterator itr = rhs.begin(); + while (itr != rhs.end()) + { + this->push_back(std::move(*itr)); + ++itr; + } + + rhs.initialise(); + } + + return *this; + } +#endif + + //************************************************************************* + /// Destructor. + //************************************************************************* + ~vector() + { + this->clear(); + } + //************************************************************************* /// Fix the internal pointers after a low level memory copy. //************************************************************************* @@ -1308,50 +1352,6 @@ namespace etl return *this; } -#if ETL_CPP11_SUPPORTED - //************************************************************************* - /// Move constructor. - //************************************************************************* - vector(vector&& other) - : etl::ivector(reinterpret_cast(&buffer), MAX_SIZE) - { - if (this != &other) - { - this->initialise(); - - typename etl::ivector::iterator itr = other.begin(); - while (itr != other.end()) - { - this->push_back(std::move(*itr)); - ++itr; - } - - other.initialise(); - } - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - vector& operator = (vector&& rhs) - { - if (&rhs != this) - { - this->clear(); - typename etl::ivector::iterator itr = rhs.begin(); - while (itr != rhs.end()) - { - this->push_back(std::move(*itr)); - ++itr; - } - - rhs.initialise(); - } - - return *this; - } -#endif - //************************************************************************* /// Fix the internal pointers after a low level memory copy. //************************************************************************* diff --git a/test/test_vector_non_trivial.cpp b/test/test_vector_non_trivial.cpp index a0dc480f..1ffdd5fb 100644 --- a/test/test_vector_non_trivial.cpp +++ b/test/test_vector_non_trivial.cpp @@ -189,6 +189,34 @@ namespace CHECK(data2 != data); } + //************************************************************************* + TEST(test_move_constructor) + { + const size_t SIZE = 10U; + typedef etl::vector, SIZE> Data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + Data data1; + data1.push_back(std::move(p1)); + data1.push_back(std::move(p2)); + data1.push_back(std::move(p3)); + data1.push_back(std::move(p4)); + + Data data2(std::move(data1)); + + CHECK_EQUAL(0U, data1.size()); + CHECK_EQUAL(4U, data2.size()); + + CHECK_EQUAL(1U, *data2[0]); + CHECK_EQUAL(2U, *data2[1]); + CHECK_EQUAL(3U, *data2[2]); + CHECK_EQUAL(4U, *data2[3]); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment) { @@ -204,6 +232,35 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST(test_move_assignment) + { + const size_t SIZE = 10U; + typedef etl::vector, SIZE> Data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + Data data1; + data1.push_back(std::move(p1)); + data1.push_back(std::move(p2)); + data1.push_back(std::move(p3)); + data1.push_back(std::move(p4)); + + Data data2; + data2 = std::move(data1); + + CHECK_EQUAL(0U, data1.size()); + CHECK_EQUAL(4U, data2.size()); + + CHECK_EQUAL(1U, *data2[0]); + CHECK_EQUAL(2U, *data2[1]); + CHECK_EQUAL(3U, *data2[2]); + CHECK_EQUAL(4U, *data2[3]); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment_iterface) { From 05bc2b83b577cfba753bf76cdde84f57a81e7144 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 30 Dec 2018 11:16:52 +0000 Subject: [PATCH 08/14] Added move member functions --- include/etl/list.h | 123 +++++++++++++++++++++++++++++++--- test/test_list.cpp | 160 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 274 insertions(+), 9 deletions(-) diff --git a/include/etl/list.h b/include/etl/list.h index ed539543..b95dc64c 100644 --- a/include/etl/list.h +++ b/include/etl/list.h @@ -46,7 +46,6 @@ SOFTWARE. #include "debug_count.h" #include "nullptr.h" #include "type_traits.h" -#include "parameter_type.h" #include "algorithm.h" #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) @@ -418,6 +417,7 @@ namespace etl typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; + typedef T&& rvalue_reference; typedef size_t size_type; protected: @@ -429,7 +429,7 @@ namespace etl //************************************************************************* struct data_node_t : public node_t { - explicit data_node_t(parameter_t value_) + explicit data_node_t(const T& value_) : value(value_) { } @@ -823,7 +823,7 @@ namespace etl //************************************************************************* /// Assigns 'n' copies of a value to the list. //************************************************************************* - void assign(size_t n, parameter_t value) + void assign(size_t n, const T& value) { #if defined(ETL_DEBUG) ETL_ASSERT(n <= available(), ETL_ERROR(list_full)); @@ -843,7 +843,7 @@ namespace etl //************************************************************************* /// Pushes a value to the front of the list. //************************************************************************* - void push_front(parameter_t value) + void push_front(const T& value) { #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(!full(), ETL_ERROR(list_full)); @@ -851,6 +851,19 @@ namespace etl insert_node(get_head(), allocate_data_node(value)); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Pushes a value to the front of the list. + //************************************************************************* + void push_front(rvalue_reference value) + { +#if defined(ETL_CHECK_PUSH_POP) + ETL_ASSERT(!full(), ETL_ERROR(list_full)); +#endif + insert_node(get_head(), allocate_data_node(std::move(value))); + } +#endif + #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) //************************************************************************* /// Emplaces a value to the front of the list. @@ -953,7 +966,7 @@ namespace etl //************************************************************************* /// Pushes a value to the back of the list. //************************************************************************* - void push_back(parameter_t value) + void push_back(const T& value) { #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(!full(), ETL_ERROR(list_full)); @@ -961,6 +974,19 @@ namespace etl insert_node(terminal_node, allocate_data_node(value)); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Pushes a value to the back of the list. + //************************************************************************* + void push_back(rvalue_reference value) + { +#if defined(ETL_CHECK_PUSH_POP) + ETL_ASSERT(!full(), ETL_ERROR(list_full)); +#endif + insert_node(terminal_node, allocate_data_node(std::move(value))); + } +#endif + //************************************************************************* /// Emplaces a value to the back of the list. //************************************************************************* @@ -1061,6 +1087,21 @@ namespace etl return iterator(data_node); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Inserts a value to the list at the specified position. + //************************************************************************* + iterator insert(iterator position, rvalue_reference value) + { + ETL_ASSERT(!full(), ETL_ERROR(list_full)); + + data_node_t& data_node = allocate_data_node(std::move(value)); + insert_node(*position.p_node, data_node); + + return iterator(data_node); + } +#endif + //************************************************************************* /// Emplaces a value to the list at the specified position. //************************************************************************* @@ -1209,7 +1250,7 @@ namespace etl //************************************************************************* /// Resizes the list. //************************************************************************* - void resize(size_t n, parameter_t value) + void resize(size_t n, const_reference value) { ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(list_full)); @@ -1675,7 +1716,7 @@ namespace etl //************************************************************************* /// Allocate a data_node_t. //************************************************************************* - data_node_t& allocate_data_node(parameter_t value) + data_node_t& allocate_data_node(const_reference value) { ETL_ASSERT(p_node_pool != nullptr, ETL_ERROR(list_no_pool)); @@ -1686,6 +1727,22 @@ namespace etl return *p_data_node; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Allocate a data_node_t. + //************************************************************************* + data_node_t& allocate_data_node(rvalue_reference value) + { + ETL_ASSERT(p_node_pool != nullptr, ETL_ERROR(list_no_pool)); + + data_node_t* p_data_node = p_node_pool->allocate(); + ::new (&(p_data_node->value)) T(std::move(value)); + ETL_INCREMENT_DEBUG_COUNT + + return *p_data_node; + } +#endif + //************************************************************************* /// Destroy a data_node_t. //************************************************************************* @@ -1731,6 +1788,7 @@ namespace etl typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; + typedef T&& rvalue_reference; typedef size_t size_type; //************************************************************************* @@ -1761,7 +1819,7 @@ namespace etl //************************************************************************* /// Construct from size and value. //************************************************************************* - list(size_t initial_size, typename ilist::parameter_t value) + list(size_t initial_size, const T& value) : etl::ilist(node_pool, MAX_SIZE, false) { this->assign(initial_size, value); @@ -1779,6 +1837,29 @@ namespace etl } } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + list(list&& other) + : etl::ilist(node_pool, MAX_SIZE, false) + { + if (this != &other) + { + this->initialise(); + + typename etl::ilist::iterator itr = other.begin(); + while (itr != other.end()) + { + this->push_back(std::move(*itr)); + ++itr; + } + + other.initialise(); + } + } +#endif + //************************************************************************* /// Construct from range. //************************************************************************* @@ -1813,6 +1894,30 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Assignment operator. + //************************************************************************* + list& operator = (list&& rhs) + { + if (&rhs != this) + { + this->initialise(); + + typename etl::ilist::iterator itr = rhs.begin(); + while (itr != rhs.end()) + { + this->push_back(std::move(*itr)); + ++itr; + } + + rhs.initialise(); + } + + return *this; + } +#endif + private: /// The pool of nodes used in the list. @@ -1873,7 +1978,7 @@ namespace etl //************************************************************************* /// Construct from size and value. //************************************************************************* - list(size_t initial_size, typename ilist::parameter_t value, etl::ipool& node_pool) + list(size_t initial_size, const T& value, etl::ipool& node_pool) : etl::ilist(node_pool, node_pool.max_size(), true) { this->assign(initial_size, value); diff --git a/test/test_list.cpp b/test/test_list.cpp index 02305747..066a4688 100644 --- a/test/test_list.cpp +++ b/test/test_list.cpp @@ -37,6 +37,7 @@ SOFTWARE. #include #include #include +#include namespace { @@ -199,6 +200,36 @@ namespace CHECK_EQUAL(compare_data.size() - 2, other_data.size()); } + //************************************************************************* + TEST(test_move_constructor) + { + const size_t SIZE = 10U; + typedef etl::list, SIZE> Data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + Data data1; + data1.push_back(std::move(p1)); + data1.push_back(std::move(p2)); + data1.push_back(std::move(p3)); + data1.push_back(std::move(p4)); + + Data data2(std::move(data1)); + + CHECK_EQUAL(0U, data1.size()); + CHECK_EQUAL(4U, data2.size()); + + Data::const_iterator itr = data2.begin(); + + CHECK_EQUAL(1U, *(*itr++)); + CHECK_EQUAL(2U, *(*itr++)); + CHECK_EQUAL(3U, *(*itr++)); + CHECK_EQUAL(4U, *(*itr++)); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_iterator) { @@ -429,6 +460,39 @@ namespace CHECK(are_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_move) + { + typedef etl::list, SIZE> Data; + + Data data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + // Move items to data. + data.insert(data.begin(), std::move(p1)); + data.insert(data.begin(), std::move(p2)); + data.insert(data.end(), std::move(p3)); + data.insert(data.begin(), std::move(p4)); + + CHECK_EQUAL(4U, data.size()); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + Data::const_iterator itr = data.begin(); + + CHECK_EQUAL(4U, *(*itr++)); + CHECK_EQUAL(2U, *(*itr++)); + CHECK_EQUAL(1U, *(*itr++)); + CHECK_EQUAL(3U, *(*itr++)); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_emplace_position_value) { @@ -554,6 +618,38 @@ namespace CHECK(are_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_front_move) + { + const size_t SIZE = 10U; + typedef etl::list, SIZE> Data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + Data data; + data.push_front(std::move(p1)); + data.push_front(std::move(p2)); + data.push_front(std::move(p3)); + data.push_front(std::move(p4)); + + CHECK_EQUAL(4U, data.size()); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + Data::const_iterator itr = data.begin(); + + CHECK_EQUAL(4U, *(*itr++)); + CHECK_EQUAL(3U, *(*itr++)); + CHECK_EQUAL(2U, *(*itr++)); + CHECK_EQUAL(1U, *(*itr++)); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_emplace_front) { @@ -681,6 +777,38 @@ namespace CHECK(are_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back_move) + { + const size_t SIZE = 10U; + typedef etl::list, SIZE> Data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + Data data; + data.push_back(std::move(p1)); + data.push_back(std::move(p2)); + data.push_back(std::move(p3)); + data.push_back(std::move(p4)); + + CHECK_EQUAL(4U, data.size()); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + Data::const_iterator itr = data.begin(); + + CHECK_EQUAL(1U, *(*itr++)); + CHECK_EQUAL(2U, *(*itr++)); + CHECK_EQUAL(3U, *(*itr++)); + CHECK_EQUAL(4U, *(*itr++)); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_emplace_back) { @@ -907,6 +1035,38 @@ namespace CHECK(are_equal); } + //************************************************************************* + TEST(test_move_assignment) + { + const size_t SIZE = 10U; + typedef etl::list, SIZE> Data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + Data data1; + data1.push_back(std::move(p1)); + data1.push_back(std::move(p2)); + data1.push_back(std::move(p3)); + data1.push_back(std::move(p4)); + + Data data2; + data2 = std::move(data1); + + CHECK_EQUAL(0U, data1.size()); + CHECK_EQUAL(4U, data2.size()); + + Data::const_iterator itr = data2.begin(); + + CHECK_EQUAL(1U, *(*itr++)); + CHECK_EQUAL(2U, *(*itr++)); + CHECK_EQUAL(3U, *(*itr++)); + CHECK_EQUAL(4U, *(*itr++)); + } + + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment_interface) { From 5e199b6bb4c5e5481d8bf3f9dbb8cbabe9b4df68 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 30 Dec 2018 11:17:17 +0000 Subject: [PATCH 09/14] Added is_rvalue_reference --- include/etl/type_traits_generator.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/etl/type_traits_generator.h b/include/etl/type_traits_generator.h index 183d74ca..83b982bd 100644 --- a/include/etl/type_traits_generator.h +++ b/include/etl/type_traits_generator.h @@ -326,6 +326,13 @@ namespace etl template struct is_trivially_copy_assignable : etl::is_pod {}; #endif +#if ETL_CPP11_SUPPORTED + /// is_rvalue_reference + ///\ingroup type_traits + template struct is_rvalue_reference : etl::false_type {}; + template struct is_rvalue_reference : etl::true_type {}; +#endif + /// conditional ///\ingroup type_traits template struct conditional { typedef T type; }; @@ -347,7 +354,7 @@ namespace etl struct conditional_integral_constant { ETL_STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); - static const T value = FALSE_VALUE; + static const T value = FALSE_VALUE; }; /// make_signed From 48aabaad54a35044f32a899ed637d85c01e27e86 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 1 Jan 2019 14:02:08 +0000 Subject: [PATCH 10/14] Added interface move assignment. Added move splice & merge. --- include/etl/list.h | 206 ++++++++++++++++++++++++++++- test/test_list.cpp | 319 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 442 insertions(+), 83 deletions(-) diff --git a/include/etl/list.h b/include/etl/list.h index b95dc64c..3d62eb17 100644 --- a/include/etl/list.h +++ b/include/etl/list.h @@ -47,6 +47,7 @@ SOFTWARE. #include "nullptr.h" #include "type_traits.h" #include "algorithm.h" +#include "memory.h" #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) #include @@ -1077,7 +1078,7 @@ namespace etl //************************************************************************* /// Inserts a value to the list at the specified position. //************************************************************************* - iterator insert(iterator position, const value_type& value) + iterator insert(iterator position, const_reference value) { ETL_ASSERT(!full(), ETL_ERROR(list_full)); @@ -1180,7 +1181,7 @@ namespace etl //************************************************************************* /// Inserts 'n' copies of a value to the list at the specified position. //************************************************************************* - void insert(iterator position, size_t n, const value_type& value) + void insert(iterator position, size_t n, const_reference value) { for (size_t i = 0; i < n; ++i) { @@ -1279,7 +1280,7 @@ namespace etl //************************************************************************* // Removes the values specified. //************************************************************************* - void remove(const value_type& value) + void remove(const_reference value) { iterator iValue = begin(); @@ -1368,6 +1369,25 @@ namespace etl } } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Splices from another list to this. + //************************************************************************* + void splice(iterator to, ilist&& other) + { + if (&other != this) + { + ilist::iterator itr = other.begin(); + while (itr != other.end()) + { + to = insert(to, std::move(*itr++)); + } + + other.erase(other.begin(), other.end()); + } + } +#endif + //************************************************************************* /// Splices an element from another list to this. //************************************************************************* @@ -1386,6 +1406,26 @@ namespace etl } } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Splices an element from another list to this. + //************************************************************************* + void splice(iterator to, ilist&& other, iterator from) + { + if (&other == this) + { + // Internal move. + move(to, from); + } + else + { + // From another list. + insert(to, std::move(*from)); + other.erase(from); + } + } +#endif + //************************************************************************* /// Splices a range of elements from another list to this. //************************************************************************* @@ -1404,6 +1444,32 @@ namespace etl } } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Splices a range of elements from another list to this. + //************************************************************************* + void splice(iterator to, ilist&& other, iterator first, iterator last) + { + if (&other == this) + { + // Internal move. + move(to, first, last); + } + else + { + // From another list. + ilist::iterator itr = first; + while (itr != last) + { + to = insert(to, std::move(*itr++)); + ++to; + } + + other.erase(first, last); + } + } +#endif + //************************************************************************* /// Merge another list into this one. Both lists should be sorted. //************************************************************************* @@ -1460,6 +1526,67 @@ namespace etl } } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Merge another list into this one. Both lists should be sorted. + //************************************************************************* + void merge(ilist&& other) + { + merge(std::move(other), std::less()); + } + + //************************************************************************* + /// Merge another list into this one. Both lists should be sorted. + //************************************************************************* + template + void merge(ilist&& other, TCompare compare) + { + if (!other.empty()) + { +#if defined(ETL_DEBUG) + ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(list_unsorted)); + ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(list_unsorted)); +#endif + + ilist::iterator other_begin = other.begin(); + ilist::iterator other_end = other.end(); + + ilist::iterator this_begin = begin(); + ilist::iterator this_end = end(); + + while ((this_begin != this_end) && (other_begin != other_end)) + { + // Find the place to insert. + while ((this_begin != this_end) && !(compare(*other_begin, *this_begin))) + { + ++this_begin; + } + + // Insert. + if (this_begin != this_end) + { + while ((other_begin != other_end) && (compare(*other_begin, *this_begin))) + { + insert(this_begin, std::move(*other_begin)); + ++other_begin; + } + } + } + + // Any left over? + if ((this_begin == this_end) && (other_begin != other_end)) + { + while (other_begin != other_end) + { + insert(this_end, std::move(*other_begin++)); + } + } + + other.clear(); + } + } +#endif + //************************************************************************* /// Sort using in-place merge sort algorithm. /// Uses 'less-than operator as the predicate. @@ -1595,6 +1722,30 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Assignment operator. + //************************************************************************* + ilist& operator = (ilist&& rhs) + { + if (&rhs != this) + { + this->initialise(); + + iterator itr = rhs.begin(); + while (itr != rhs.end()) + { + push_back(std::move(*itr)); + ++itr; + } + + rhs.initialise(); + } + + return *this; + } +#endif + protected: //************************************************************************* @@ -1772,7 +1923,6 @@ namespace etl //************************************************************************* /// A templated list implementation that uses a fixed size buffer. - ///\note 'merge' and 'splice' and are not supported. //************************************************************************* template class list : public etl::ilist @@ -1926,7 +2076,6 @@ namespace etl //************************************************************************* /// A templated list implementation that uses a fixed size buffer. - ///\note 'merge' and 'splice' and are not supported. //************************************************************************* template class list : public etl::ilist @@ -1996,6 +2145,29 @@ namespace etl } } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + list(list&& other) + : etl::ilist(*other.p_node_pool, other.p_node_pool->max_size(), true) + { + if (this != &other) + { + this->initialise(); + + typename etl::ilist::iterator itr = other.begin(); + while (itr != other.end()) + { + this->push_back(std::move(*itr)); + ++itr; + } + + other.initialise(); + } + } +#endif + //************************************************************************* /// Construct from range. //************************************************************************* @@ -2030,6 +2202,30 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Assignment operator. + //************************************************************************* + list& operator = (list&& rhs) + { + if (&rhs != this) + { + this->initialise(); + + typename etl::ilist::iterator itr = rhs.begin(); + while (itr != rhs.end()) + { + this->push_back(std::move(*itr)); + ++itr; + } + + rhs.initialise(); + } + + return *this; + } +#endif + //************************************************************************* /// Set the pool instance. //************************************************************************* diff --git a/test/test_list.cpp b/test/test_list.cpp index 066a4688..2fa024cb 100644 --- a/test/test_list.cpp +++ b/test/test_list.cpp @@ -37,7 +37,7 @@ SOFTWARE. #include #include #include -#include + namespace { @@ -45,6 +45,7 @@ namespace { typedef TestDataDC ItemDC; typedef TestDataNDC ItemNDC; + typedef TestDataM ItemM; const size_t SIZE = 10; @@ -55,6 +56,9 @@ namespace typedef etl::list DataInt; + typedef etl::list DataM; + typedef etl::ilist IDataM; + typedef std::list CompareData; typedef std::vector InitialData; @@ -203,31 +207,33 @@ namespace //************************************************************************* TEST(test_move_constructor) { - const size_t SIZE = 10U; - typedef etl::list, SIZE> Data; + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); - std::unique_ptr p1(new uint32_t(1U)); - std::unique_ptr p2(new uint32_t(2U)); - std::unique_ptr p3(new uint32_t(3U)); - std::unique_ptr p4(new uint32_t(4U)); - - Data data1; + DataM data1; data1.push_back(std::move(p1)); data1.push_back(std::move(p2)); data1.push_back(std::move(p3)); data1.push_back(std::move(p4)); - Data data2(std::move(data1)); + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + DataM data2(std::move(data1)); CHECK_EQUAL(0U, data1.size()); CHECK_EQUAL(4U, data2.size()); - Data::const_iterator itr = data2.begin(); + DataM::const_iterator itr = data2.begin(); - CHECK_EQUAL(1U, *(*itr++)); - CHECK_EQUAL(2U, *(*itr++)); - CHECK_EQUAL(3U, *(*itr++)); - CHECK_EQUAL(4U, *(*itr++)); + CHECK_EQUAL(1U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(4U, (*itr++).value); } //************************************************************************* @@ -463,34 +469,30 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_move) { - typedef etl::list, SIZE> Data; + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); - Data data; + DataM data1; + data1.insert(data1.begin(), std::move(p1)); + data1.insert(data1.begin(), std::move(p2)); + data1.insert(data1.begin(), std::move(p3)); + data1.insert(data1.begin(), std::move(p4)); - std::unique_ptr p1(new uint32_t(1U)); - std::unique_ptr p2(new uint32_t(2U)); - std::unique_ptr p3(new uint32_t(3U)); - std::unique_ptr p4(new uint32_t(4U)); - - // Move items to data. - data.insert(data.begin(), std::move(p1)); - data.insert(data.begin(), std::move(p2)); - data.insert(data.end(), std::move(p3)); - data.insert(data.begin(), std::move(p4)); - - CHECK_EQUAL(4U, data.size()); + CHECK_EQUAL(4U, data1.size()); CHECK(!bool(p1)); CHECK(!bool(p2)); CHECK(!bool(p3)); CHECK(!bool(p4)); - Data::const_iterator itr = data.begin(); + DataM::const_iterator itr = data1.begin(); - CHECK_EQUAL(4U, *(*itr++)); - CHECK_EQUAL(2U, *(*itr++)); - CHECK_EQUAL(1U, *(*itr++)); - CHECK_EQUAL(3U, *(*itr++)); + CHECK_EQUAL(4U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(1U, (*itr++).value); } //************************************************************************* @@ -621,15 +623,12 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_push_front_move) { - const size_t SIZE = 10U; - typedef etl::list, SIZE> Data; + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); - std::unique_ptr p1(new uint32_t(1U)); - std::unique_ptr p2(new uint32_t(2U)); - std::unique_ptr p3(new uint32_t(3U)); - std::unique_ptr p4(new uint32_t(4U)); - - Data data; + DataM data; data.push_front(std::move(p1)); data.push_front(std::move(p2)); data.push_front(std::move(p3)); @@ -642,12 +641,12 @@ namespace CHECK(!bool(p3)); CHECK(!bool(p4)); - Data::const_iterator itr = data.begin(); + DataM::const_iterator itr = data.begin(); - CHECK_EQUAL(4U, *(*itr++)); - CHECK_EQUAL(3U, *(*itr++)); - CHECK_EQUAL(2U, *(*itr++)); - CHECK_EQUAL(1U, *(*itr++)); + CHECK_EQUAL(4U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(1U, (*itr++).value); } //************************************************************************* @@ -780,15 +779,12 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_push_back_move) { - const size_t SIZE = 10U; - typedef etl::list, SIZE> Data; + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); - std::unique_ptr p1(new uint32_t(1U)); - std::unique_ptr p2(new uint32_t(2U)); - std::unique_ptr p3(new uint32_t(3U)); - std::unique_ptr p4(new uint32_t(4U)); - - Data data; + DataM data; data.push_back(std::move(p1)); data.push_back(std::move(p2)); data.push_back(std::move(p3)); @@ -801,12 +797,12 @@ namespace CHECK(!bool(p3)); CHECK(!bool(p4)); - Data::const_iterator itr = data.begin(); + DataM::const_iterator itr = data.begin(); - CHECK_EQUAL(1U, *(*itr++)); - CHECK_EQUAL(2U, *(*itr++)); - CHECK_EQUAL(3U, *(*itr++)); - CHECK_EQUAL(4U, *(*itr++)); + CHECK_EQUAL(1U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(4U, (*itr++).value); } //************************************************************************* @@ -1022,7 +1018,6 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment) { - CompareData compare_data(sorted_data.begin(), sorted_data.end()); DataNDC data(sorted_data.begin(), sorted_data.end()); DataNDC other_data; @@ -1038,35 +1033,31 @@ namespace //************************************************************************* TEST(test_move_assignment) { - const size_t SIZE = 10U; - typedef etl::list, SIZE> Data; + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); - std::unique_ptr p1(new uint32_t(1U)); - std::unique_ptr p2(new uint32_t(2U)); - std::unique_ptr p3(new uint32_t(3U)); - std::unique_ptr p4(new uint32_t(4U)); - - Data data1; + DataM data1; data1.push_back(std::move(p1)); data1.push_back(std::move(p2)); data1.push_back(std::move(p3)); data1.push_back(std::move(p4)); - Data data2; + DataM data2; data2 = std::move(data1); CHECK_EQUAL(0U, data1.size()); CHECK_EQUAL(4U, data2.size()); - Data::const_iterator itr = data2.begin(); + DataM::const_iterator itr = data2.begin(); - CHECK_EQUAL(1U, *(*itr++)); - CHECK_EQUAL(2U, *(*itr++)); - CHECK_EQUAL(3U, *(*itr++)); - CHECK_EQUAL(4U, *(*itr++)); + CHECK_EQUAL(1U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(4U, (*itr++).value); } - //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment_interface) { @@ -1086,6 +1077,38 @@ namespace CHECK(are_equal); } + //************************************************************************* + TEST(test_move_assignment_interface) + { + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); + + DataM data1; + data1.push_back(std::move(p1)); + data1.push_back(std::move(p2)); + data1.push_back(std::move(p3)); + data1.push_back(std::move(p4)); + + DataM data2; + + IDataM& idata1 = data1; + IDataM& idata2 = data2; + + idata2 = std::move(idata1); + + CHECK_EQUAL(0U, data1.size()); + CHECK_EQUAL(4U, data2.size()); + + DataM::const_iterator itr = data2.begin(); + + CHECK_EQUAL(1U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(4U, (*itr++).value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_self_assignment) { @@ -1725,6 +1748,7 @@ namespace DataNDC2 data0(merge_data0.begin(), merge_data0.end()); DataNDC2 data1(merge_data1.begin(), merge_data1.end()); + CompareData compare0(merge_data0.begin(), merge_data0.end()); CompareData compare1(merge_data1.begin(), merge_data1.end()); @@ -1804,8 +1828,6 @@ namespace data0.reverse(); data1.reverse(); - - CompareData compare0(merge_data0.begin(), merge_data0.end()); CompareData compare1(merge_data1.begin(), merge_data1.end()); @@ -1830,5 +1852,146 @@ namespace CHECK_THROW(data0.merge(data1), etl::list_unsorted); } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_merge_move) + { + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); + + ItemM p5(5U); + ItemM p6(6U); + ItemM p7(7U); + ItemM p8(8U); + + DataM data1; + data1.push_back(std::move(p1)); + data1.push_back(std::move(p2)); + data1.push_back(std::move(p3)); + data1.push_back(std::move(p4)); + + DataM data2; + data2.push_back(std::move(p5)); + data2.push_back(std::move(p6)); + data2.push_back(std::move(p7)); + data2.push_back(std::move(p8)); + + data1.merge(std::move(data2)); + + CHECK_EQUAL(8U, data1.size()); + CHECK_EQUAL(0U, data2.size()); + + DataM::const_iterator itr = data1.begin(); + + CHECK_EQUAL(1U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(4U, (*itr++).value); + CHECK_EQUAL(5U, (*itr++).value); + CHECK_EQUAL(6U, (*itr++).value); + CHECK_EQUAL(7U, (*itr++).value); + CHECK_EQUAL(8U, (*itr++).value); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_splice_move_range_same) + { + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); + ItemM p5(5U); + ItemM p6(6U); + ItemM p7(7U); + ItemM p8(8U); + + DataM data; + data.push_back(std::move(p1)); + data.push_back(std::move(p2)); + data.push_back(std::move(p3)); + data.push_back(std::move(p4)); + data.push_back(std::move(p5)); + data.push_back(std::move(p6)); + data.push_back(std::move(p7)); + data.push_back(std::move(p8)); + + DataM::iterator begin; + DataM::iterator end; + DataM::iterator to; + + // Move nearby. + begin = data.begin(); + std::advance(begin, 4); + end = begin; + std::advance(end, 2); + to = data.begin(); + std::advance(to, 2); + data.splice(to, std::move(data), begin, end); + + CHECK_EQUAL(8U, data.size()); + + DataM::const_iterator itr = data.begin(); + + CHECK_EQUAL(1U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(5U, (*itr++).value); + CHECK_EQUAL(6U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(4U, (*itr++).value); + CHECK_EQUAL(7U, (*itr++).value); + CHECK_EQUAL(8U, (*itr++).value); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_splice_move_range_different) + { + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); + ItemM p5(5U); + ItemM p6(6U); + ItemM p7(7U); + ItemM p8(8U); + + DataM data1; + data1.push_back(std::move(p1)); + data1.push_back(std::move(p2)); + data1.push_back(std::move(p3)); + data1.push_back(std::move(p4)); + + DataM data2; + data2.push_back(std::move(p5)); + data2.push_back(std::move(p6)); + data2.push_back(std::move(p7)); + data2.push_back(std::move(p8)); + + DataM::iterator begin; + DataM::iterator end; + DataM::iterator to; + + // Move. + begin = data2.begin(); + std::advance(begin, 1); + end = begin; + std::advance(end, 2); + to = data1.begin(); + std::advance(to, 2); + data1.splice(to, std::move(data2), begin, end); + + CHECK_EQUAL(6U, data1.size()); + CHECK_EQUAL(2U, data2.size()); + + DataM::const_iterator itr = data1.begin(); + + CHECK_EQUAL(1U, (*itr++).value); // 1 + CHECK_EQUAL(2U, (*itr++).value); // 2 + CHECK_EQUAL(6U, (*itr++).value); // 7 + CHECK_EQUAL(7U, (*itr++).value); // 6 + CHECK_EQUAL(3U, (*itr++).value); // 3 + CHECK_EQUAL(4U, (*itr++).value); // 4 + } }; } From 6b165aee54a0626ed0c14578b3e04299d5af9ec1 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 1 Jan 2019 14:02:43 +0000 Subject: [PATCH 11/14] Added interface move assignment. --- include/etl/vector.h | 37 ++++++++++++++++++++++++++------ test/test_vector_non_trivial.cpp | 34 +++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/include/etl/vector.h b/include/etl/vector.h index ab975fbd..8b3cf069 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -40,7 +40,6 @@ SOFTWARE. #include "platform.h" #include "algorithm.h" #include "type_traits.h" -#include "parameter_type.h" #include "error_handler.h" #include "memory.h" #include "container.h" @@ -86,6 +85,7 @@ namespace etl typedef T value_type; typedef T& reference; typedef const T& const_reference; + typedef T&& rvalue_reference; typedef T* pointer; typedef const T* const_pointer; typedef T* iterator; @@ -405,7 +405,7 @@ namespace etl /// If asserts or exceptions are enabled, emits vector_full if the vector is already full. ///\param value The value to add. //********************************************************************* - void push_back(const T& value) + void push_back(const_reference value) { #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(size() != CAPACITY, ETL_ERROR(vector_full)); @@ -419,7 +419,7 @@ namespace etl /// If asserts or exceptions are enabled, emits vector_full if the vector is already full. ///\param value The value to add. //********************************************************************* - void push_back(T&& value) + void push_back(rvalue_reference value) { #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(size() != CAPACITY, ETL_ERROR(vector_full)); @@ -528,7 +528,7 @@ namespace etl ///\param position The position to insert before. ///\param value The value to insert. //********************************************************************* - iterator insert(iterator position, const T& value) + iterator insert(iterator position, const_reference value) { ETL_ASSERT(size() + 1 <= CAPACITY, ETL_ERROR(vector_full)); @@ -553,7 +553,7 @@ namespace etl ///\param position The position to insert before. ///\param value The value to insert. //********************************************************************* - iterator insert(iterator position, T&& value) + iterator insert(iterator position, rvalue_reference value) { ETL_ASSERT(size() + 1 <= CAPACITY, ETL_ERROR(vector_full)); @@ -866,6 +866,29 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + ivector& operator = (ivector&& rhs) + { + if (&rhs != this) + { + clear(); + iterator itr = rhs.begin(); + while (itr != rhs.end()) + { + push_back(std::move(*itr)); + ++itr; + } + + rhs.initialise(); + } + + return *this; + } +#endif + //************************************************************************* /// Gets the current size of the vector. ///\return The current size of the vector. @@ -961,7 +984,7 @@ namespace etl //********************************************************************* /// Create a new element with a value at the back //********************************************************************* - inline void create_back(const T& value) + inline void create_back(const_reference value) { etl::create_copy_at(p_end, value); ETL_INCREMENT_DEBUG_COUNT @@ -973,7 +996,7 @@ namespace etl //********************************************************************* /// Create a new element with a value at the back //********************************************************************* - inline void create_back(T&& value) + inline void create_back(rvalue_reference value) { etl::create_copy_at(p_end, std::move(value)); ETL_INCREMENT_DEBUG_COUNT diff --git a/test/test_vector_non_trivial.cpp b/test/test_vector_non_trivial.cpp index 1ffdd5fb..530779f2 100644 --- a/test/test_vector_non_trivial.cpp +++ b/test/test_vector_non_trivial.cpp @@ -279,6 +279,40 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST(test_move_assignment_interface) + { + const size_t SIZE = 10U; + typedef etl::vector, SIZE> Data; + typedef etl::ivector> IData; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + Data data1; + data1.push_back(std::move(p1)); + data1.push_back(std::move(p2)); + data1.push_back(std::move(p3)); + data1.push_back(std::move(p4)); + + Data data2; + + IData& idata1 = data1; + IData& idata2 = data2; + + idata2 = std::move(idata1); + + CHECK_EQUAL(0U, data1.size()); + CHECK_EQUAL(4U, data2.size()); + + CHECK_EQUAL(1U, *data2[0]); + CHECK_EQUAL(2U, *data2[1]); + CHECK_EQUAL(3U, *data2[2]); + CHECK_EQUAL(4U, *data2[3]); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_self_assignment) { From 96ce602874ba28135b8205ed0805de562d131200 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 1 Jan 2019 14:03:02 +0000 Subject: [PATCH 12/14] Added interface move assignment. --- include/etl/deque.h | 24 +++++++++++++++++++++++- test/test_deque.cpp | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/include/etl/deque.h b/include/etl/deque.h index b829da5d..f44389e2 100644 --- a/include/etl/deque.h +++ b/include/etl/deque.h @@ -49,7 +49,6 @@ SOFTWARE. #include "debug_count.h" #include "algorithm.h" #include "type_traits.h" -#include "parameter_type.h" #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) #include @@ -1948,6 +1947,29 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + ideque& operator =(ideque&& rhs) + { + if (&rhs != this) + { + clear(); + iterator itr = rhs.begin(); + while (itr != rhs.end()) + { + push_back(std::move(*itr)); + ++itr; + } + + rhs.initialise(); + } + + return *this; + } +#endif + #ifdef ETL_IDEQUE_REPAIR_ENABLE //************************************************************************* /// Fix the internal pointers after a low level memory copy. diff --git a/test/test_deque.cpp b/test/test_deque.cpp index 5c1a21f3..44cdcf84 100644 --- a/test/test_deque.cpp +++ b/test/test_deque.cpp @@ -240,6 +240,40 @@ namespace CHECK(std::equal(deque1.begin(), deque1.end(), deque2.begin())); } + //************************************************************************* + TEST(test_move_assignment_interface) + { + const size_t SIZE = 10U; + typedef etl::deque, SIZE> Data; + typedef etl::ideque> IData; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + Data deque1; + deque1.push_back(std::move(p1)); + deque1.push_back(std::move(p2)); + deque1.push_back(std::move(p3)); + deque1.push_back(std::move(p4)); + + Data deque2; + + IData& ideque1 = deque1; + IData& ideque2 = deque2; + + ideque2 = std::move(ideque1); + + CHECK_EQUAL(0U, deque1.size()); + CHECK_EQUAL(4U, deque2.size()); + + CHECK_EQUAL(1U, *deque2[0]); + CHECK_EQUAL(2U, *deque2[1]); + CHECK_EQUAL(3U, *deque2[2]); + CHECK_EQUAL(4U, *deque2[3]); + } + //************************************************************************* TEST(test_self_assignment) { From cae432fc319b0650254b3cdd2b86867fb2ead909 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 1 Jan 2019 14:03:21 +0000 Subject: [PATCH 13/14] Added move only data type --- test/data.h | 85 +++++++++++++++++++++++++++++++++ test/vs2017/etl.vcxproj | 1 + test/vs2017/etl.vcxproj.filters | 3 ++ 3 files changed, 89 insertions(+) diff --git a/test/data.h b/test/data.h index c43769e8..14b5f47c 100644 --- a/test/data.h +++ b/test/data.h @@ -152,4 +152,89 @@ std::ostream& operator << (std::ostream& s, const TestDataNDC& rhs) return s; } +//***************************************************************************** +// Movable. +//***************************************************************************** +template +class TestDataM : public etl::instance_count> +{ +public: + + explicit TestDataM(const T& value_) + : value(value_) + , valid(true) + { + } + + TestDataM(TestDataM&& other) + : value(other.value) + , valid(true) + { + other.value = T(); + other.valid = false; + } + + TestDataM& operator =(TestDataM&& other) + { + value = other.value; + valid = true; + + other.value = T(); + other.valid = false; + } + + bool operator < (const TestDataM& other) const + { + return value < other.value; + } + + bool operator > (const TestDataM& other) const + { + return other.value < value; + } + + bool operator <= (const TestDataM& other) const + { + return !(other.value < value); + } + + bool operator >= (const TestDataM& other) const + { + return !(value < other.value); + } + + operator bool() const + { + return valid; + } + + T value; + bool valid; + +private: + + TestDataM(const TestDataM& other) = delete; + TestDataM& operator =(const TestDataM& other) = delete; +}; + +template +bool operator == (const TestDataM& lhs, const TestDataM& rhs) +{ + return lhs.value == rhs.value; +} + +template +bool operator != (const TestDataM& lhs, const TestDataM& rhs) +{ + return lhs.value != rhs.value; +} + +template +std::ostream& operator << (std::ostream& s, const TestDataM& rhs) +{ + s << rhs.value; + return s; +} + + #endif diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index 961afff0..6679be4f 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -532,6 +532,7 @@ + diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index 84162b51..161a765b 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -720,6 +720,9 @@ ETL\Maths + + Source Files + From 48379a8ff25bd7efd3d3872db264c56b977a2379 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 5 Jan 2019 11:34:24 +0000 Subject: [PATCH 14/14] Merge branch 'development' into feature/rvalue-references --- include/etl/algorithm.h | 15 ++++-- include/etl/flat_map.h | 28 ++++------- include/etl/flat_set.h | 12 ++--- include/etl/reference_flat_map.h | 4 +- include/etl/reference_flat_multimap.h | 2 +- include/etl/reference_flat_multiset.h | 4 +- include/etl/reference_flat_set.h | 2 +- include/etl/scheduler.h | 2 +- include/etl/version.h | 2 +- support/Release notes.txt | 4 ++ test/CMakeLists.txt | 2 - test/test_flat_map.cpp | 69 ++++++++++++++++++++++----- 12 files changed, 95 insertions(+), 51 deletions(-) diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index a705f986..65a23687 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -1127,8 +1127,8 @@ namespace etl /// Uses users defined comparison. ///\ingroup algorithm //*************************************************************************** - template ::value_type> > - void sort(TIterator first, TIterator last, TCompare compare = TCompare()) + template + void sort(TIterator first, TIterator last, TCompare compare) { typedef typename std::iterator_traits::difference_type difference_t; @@ -1154,7 +1154,16 @@ namespace etl } } } + + //*************************************************************************** + /// Sorts the elements using shell sort. + ///\ingroup algorithm + //*************************************************************************** + template + void sort(TIterator first, TIterator last) + { + etl::sort(first, last, std::less::value_type>()); + } } #endif - diff --git a/include/etl/flat_map.h b/include/etl/flat_map.h index 2f9771bc..1d83deac 100644 --- a/include/etl/flat_map.h +++ b/include/etl/flat_map.h @@ -38,6 +38,7 @@ SOFTWARE. #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) #include #endif +#include "stl/utility.h" #undef ETL_FILE #define ETL_FILE "2" @@ -229,20 +230,7 @@ namespace etl //********************************************************************* mapped_type& operator [](key_parameter_t key) { - iterator i_element = lower_bound(key); - - // Doesn't already exist? - if (i_element == end()) - { - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(); - ETL_INCREMENT_DEBUG_COUNT - - std::pair result = refmap_t::insert_at(i_element, *pvalue); - i_element->second = result.first->second; - } - - return i_element->second; + return insert(std::make_pair(key, mapped_type())).first->second; } //********************************************************************* @@ -302,7 +290,7 @@ namespace etl std::pair result(i_element, false); // Doesn't already exist? - if ((i_element == end()) || compare(i_element->first, value.first) || compare(value.first, i_element->first)) + if ((i_element == end()) || compare(value.first, i_element->first)) { ETL_ASSERT(!refmap_t::full(), ETL_ERROR(flat_map_full)); @@ -369,7 +357,7 @@ namespace etl std::pair result(i_element, false); // Doesn't already exist? - if ((i_element == end() || (i_element->first != key))) + if ((i_element == end()) || compare(key, i_element->first)) { ETL_INCREMENT_DEBUG_COUNT result = refmap_t::insert_at(i_element, *pvalue); @@ -403,7 +391,7 @@ namespace etl std::pair result(i_element, false); // Doesn't already exist? - if ((i_element == end() || (i_element->first != key))) + if ((i_element == end()) || compare(key, i_element->first)) { ETL_INCREMENT_DEBUG_COUNT result = refmap_t::insert_at(i_element, *pvalue); @@ -435,7 +423,7 @@ namespace etl std::pair result(i_element, false); // Doesn't already exist? - if ((i_element == end() || (i_element->first != key))) + if ((i_element == end()) || compare(key, i_element->first)) { ETL_INCREMENT_DEBUG_COUNT result = refmap_t::insert_at(i_element, *pvalue); @@ -467,7 +455,7 @@ namespace etl std::pair result(i_element, false); // Doesn't already exist? - if ((i_element == end() || (i_element->first != key))) + if ((i_element == end()) || compare(key, i_element->first)) { ETL_INCREMENT_DEBUG_COUNT result = refmap_t::insert_at(i_element, *pvalue); @@ -499,7 +487,7 @@ namespace etl std::pair result(i_element, false); // Doesn't already exist? - if ((i_element == end() || (i_element->first != key))) + if ((i_element == end()) || compare(key, i_element->first)) { ETL_INCREMENT_DEBUG_COUNT result = refmap_t::insert_at(i_element, *pvalue); diff --git a/include/etl/flat_set.h b/include/etl/flat_set.h index 17e08554..2d75a8d6 100644 --- a/include/etl/flat_set.h +++ b/include/etl/flat_set.h @@ -233,7 +233,7 @@ namespace etl std::pair result(i_element, false); // Doesn't already exist? - if ((i_element == end()) || compare(*i_element, value) || compare(value, *i_element)) + if ((i_element == end()) || compare(value, *i_element)) { ETL_ASSERT(!refset_t::full(), ETL_ERROR(flat_set_full)); @@ -299,7 +299,7 @@ namespace etl iterator i_element = lower_bound(*pvalue); // Doesn't already exist? - if ((i_element == end() || (*i_element != *pvalue))) + if ((i_element == end()) || compare(*pvalue, *i_element)) { ETL_INCREMENT_DEBUG_COUNT result = refset_t::insert_at(i_element, *pvalue); @@ -332,7 +332,7 @@ namespace etl iterator i_element = lower_bound(*pvalue); // Doesn't already exist? - if ((i_element == end() || (*i_element != *pvalue))) + if ((i_element == end()) || compare(*pvalue, *i_element)) { ETL_INCREMENT_DEBUG_COUNT result = refset_t::insert_at(i_element, *pvalue); @@ -365,7 +365,7 @@ namespace etl iterator i_element = lower_bound(*pvalue); // Doesn't already exist? - if ((i_element == end() || (*i_element != *pvalue))) + if ((i_element == end()) || compare(*pvalue, *i_element)) { ETL_INCREMENT_DEBUG_COUNT result = refset_t::insert_at(i_element, *pvalue); @@ -398,7 +398,7 @@ namespace etl iterator i_element = lower_bound(*pvalue); // Doesn't already exist? - if ((i_element == end() || (*i_element != *pvalue))) + if ((i_element == end()) || compare(*pvalue, *i_element)) { ETL_INCREMENT_DEBUG_COUNT result = refset_t::insert_at(i_element, *pvalue); @@ -431,7 +431,7 @@ namespace etl iterator i_element = lower_bound(*pvalue); // Doesn't already exist? - if ((i_element == end() || (*i_element != *pvalue))) + if ((i_element == end()) || compare(*pvalue, *i_element)) { ETL_INCREMENT_DEBUG_COUNT result = refset_t::insert_at(i_element, *pvalue); diff --git a/include/etl/reference_flat_map.h b/include/etl/reference_flat_map.h index 840b7497..e0392d18 100644 --- a/include/etl/reference_flat_map.h +++ b/include/etl/reference_flat_map.h @@ -238,7 +238,7 @@ namespace etl { } - const_iterator(const iterator& other) + const_iterator(const typename ireference_flat_map::iterator& other) : ilookup(other.ilookup) { } @@ -248,7 +248,7 @@ namespace etl { } - const_iterator& operator =(const iterator& other) + const_iterator& operator =(const typename ireference_flat_map::iterator& other) { ilookup = other.ilookup; return *this; diff --git a/include/etl/reference_flat_multimap.h b/include/etl/reference_flat_multimap.h index 88adde96..f4051566 100644 --- a/include/etl/reference_flat_multimap.h +++ b/include/etl/reference_flat_multimap.h @@ -213,7 +213,7 @@ namespace etl { } - const_iterator(const iterator& other) + const_iterator(const typename ireference_flat_multimap::iterator& other) : ilookup(other.ilookup) { } diff --git a/include/etl/reference_flat_multiset.h b/include/etl/reference_flat_multiset.h index 8c63f6ff..0b612f37 100644 --- a/include/etl/reference_flat_multiset.h +++ b/include/etl/reference_flat_multiset.h @@ -232,7 +232,7 @@ namespace etl { } - const_iterator(const iterator& other) + const_iterator(const typename ireference_flat_multiset::iterator& other) : ilookup(other.ilookup) { } @@ -460,7 +460,7 @@ namespace etl { std::pair result(end(), false); - ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_multiset_full)); + ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_multiset_full)); iterator i_element = std::lower_bound(begin(), end(), value, compare); diff --git a/include/etl/reference_flat_set.h b/include/etl/reference_flat_set.h index 7e934307..7a34c743 100644 --- a/include/etl/reference_flat_set.h +++ b/include/etl/reference_flat_set.h @@ -232,7 +232,7 @@ namespace etl { } - const_iterator(const iterator& other) + const_iterator(const typename ireference_flat_set::iterator& other) : ilookup(other.ilookup) { } diff --git a/include/etl/scheduler.h b/include/etl/scheduler.h index 218f4fe5..d8d645cd 100644 --- a/include/etl/scheduler.h +++ b/include/etl/scheduler.h @@ -281,7 +281,7 @@ namespace etl //******************************************* void add_task(etl::task& task) { - ETL_ASSERT(!task_list.full(), ETL_ERROR(etl::scheduler_too_many_tasks_exception)) + ETL_ASSERT(!task_list.full(), ETL_ERROR(etl::scheduler_too_many_tasks_exception)); if (!task_list.full()) { diff --git a/include/etl/version.h b/include/etl/version.h index 5339759e..833856aa 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -39,7 +39,7 @@ SOFTWARE. #define ETL_VERSION_MAJOR 14 #define ETL_VERSION_MINOR 6 -#define ETL_VERSION_PATCH 0 +#define ETL_VERSION_PATCH 1 #define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) ETL_STRINGIFY(ETL_VERSION_MINOR) ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_WIDE_STRING(ETL_CONCAT(ETL_CONCAT(ETL_VERSION_MAJOR, ETL_VERSION_MINOR), ETL_VERSION_PATCH)) diff --git a/support/Release notes.txt b/support/Release notes.txt index 873008fb..a989ff64 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +14.6.1 +Fixed bugs in etl::flat_map 'operator[]' and 'insert'. + =============================================================================== 14.6.0 Added etl::scaled_rounding to allow selection of rounding algorithms when diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 05f96eaf..690e669e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -118,8 +118,6 @@ set(TEST_SOURCE_FILES test_xor_checksum.cpp test_xor_rotate_checksum.cpp - ${CMAKE_SOURCE_DIR}/src/crc16_modbus.cpp - # Compile the source level ecl_timer here as test has provided a ecl_user.h file ${PROJECT_SOURCE_DIR}/../src/c/ecl_timer.c ) diff --git a/test/test_flat_map.cpp b/test/test_flat_map.cpp index 456bf688..efc6a81d 100644 --- a/test/test_flat_map.cpp +++ b/test/test_flat_map.cpp @@ -458,6 +458,36 @@ namespace CHECK_EQUAL(compare_data[9], data[9]); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_index_assign) + { + Compare_DataDC compare_data(initial_data_dc.begin(), initial_data_dc.end()); + + DataDC data; + + data[initial_data_dc[0].first] = initial_data_dc[0].second; + data[initial_data_dc[2].first] = initial_data_dc[2].second; + data[initial_data_dc[3].first] = initial_data_dc[3].second; + data[initial_data_dc[1].first] = initial_data_dc[1].second; + data[initial_data_dc[4].first] = initial_data_dc[4].second; + data[initial_data_dc[5].first] = initial_data_dc[5].second; + data[initial_data_dc[8].first] = initial_data_dc[8].second; + data[initial_data_dc[6].first] = initial_data_dc[6].second; + data[initial_data_dc[7].first] = initial_data_dc[7].second; + data[initial_data_dc[9].first] = initial_data_dc[9].second; + + CHECK_EQUAL(compare_data[0], data[0]); + CHECK_EQUAL(compare_data[1], data[1]); + CHECK_EQUAL(compare_data[2], data[2]); + CHECK_EQUAL(compare_data[3], data[3]); + CHECK_EQUAL(compare_data[4], data[4]); + CHECK_EQUAL(compare_data[5], data[5]); + CHECK_EQUAL(compare_data[6], data[6]); + CHECK_EQUAL(compare_data[7], data[7]); + CHECK_EQUAL(compare_data[8], data[8]); + CHECK_EQUAL(compare_data[9], data[9]); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_index_value_changed) { @@ -636,24 +666,39 @@ namespace Compare_DataNDC compare_data; DataNDC data; - data.insert(std::make_pair(0, N0)); - compare_data.insert(std::make_pair(0, N0)); + std::pair dr; + std::pair cr; - data.insert(std::make_pair(1, N1)); - compare_data.insert(std::make_pair(1, N1)); + dr = data.insert(std::make_pair(0, N0)); + cr = compare_data.insert(std::make_pair(0, N0)); + CHECK(dr.first->first == cr.first->first); + CHECK(dr.second == cr.second); - data.insert(std::make_pair(2, N2)); - compare_data.insert(std::make_pair(2, N2)); + dr = data.insert(std::make_pair(1, N1)); + cr = compare_data.insert(std::make_pair(1, N1)); + CHECK(dr.first->first == cr.first->first); + CHECK(dr.second == cr.second); + + dr = data.insert(std::make_pair(2, N2)); + cr = compare_data.insert(std::make_pair(2, N2)); + CHECK(dr.first->first == cr.first->first); + CHECK(dr.second == cr.second); // Do it again. - data.insert(std::make_pair(0, N0)); - compare_data.insert(std::make_pair(0, N0)); + dr = data.insert(std::make_pair(0, N0)); + cr = compare_data.insert(std::make_pair(0, N0)); + CHECK(dr.first->first == cr.first->first); + CHECK(dr.second == cr.second); - data.insert(std::make_pair(1, N1)); - compare_data.insert(std::make_pair(1, N1)); + dr = data.insert(std::make_pair(1, N1)); + cr = compare_data.insert(std::make_pair(1, N1)); + CHECK(dr.first->first == cr.first->first); + CHECK(dr.second == cr.second); - data.insert(std::make_pair(2, N2)); - compare_data.insert(std::make_pair(2, N2)); + dr = data.insert(std::make_pair(2, N2)); + cr = compare_data.insert(std::make_pair(2, N2)); + CHECK(dr.first->first == cr.first->first); + CHECK(dr.second == cr.second); CHECK_EQUAL(compare_data.size(), data.size());