From 4b1aa0d6b58a84c4b038532570a2952e3b8ec96b Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 14 Feb 2019 12:52:06 +0100 Subject: [PATCH] Merge remote-tracking branch 'origin/feature/rvalue-references' into development # Conflicts: # include/etl/version.h # support/Release notes.txt --- include/etl/forward_list.h | 168 +++++++++++++++++++++++++++++++++---- include/etl/version.h | 4 +- support/Release notes.txt | 4 + test/test_forward_list.cpp | 125 +++++++++++++++++++++++++++ 4 files changed, 283 insertions(+), 18 deletions(-) diff --git a/include/etl/forward_list.h b/include/etl/forward_list.h index 038e5de3..a858e621 100644 --- a/include/etl/forward_list.h +++ b/include/etl/forward_list.h @@ -38,6 +38,7 @@ SOFTWARE. #include "stl/algorithm.h" #include "stl/iterator.h" #include "stl/functional.h" +#include "stl/utility.h" #include "pool.h" #include "container.h" @@ -377,6 +378,10 @@ namespace etl typedef const T& const_reference; typedef size_t size_type; +#if ETL_CPP11_SUPPORTED + typedef T&& rvalue_reference; +#endif + protected: //************************************************************************* @@ -717,7 +722,22 @@ namespace etl insert_node_after(start_node, data_node); } -#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Pushes a value to the front of the forward_list. + //************************************************************************* + void push_front(rvalue_reference value) + { +#if defined(ETL_CHECK_PUSH_POP) + ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); +#endif + + data_node_t& data_node = allocate_data_node(std::move(value)); + insert_node_after(start_node, data_node); + } +#endif + +#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) //************************************************************************* /// Emplaces a value to the front of the list.. //************************************************************************* @@ -792,7 +812,7 @@ namespace etl ETL_INCREMENT_DEBUG_COUNT insert_node_after(start_node, *p_data_node); } -#endif // ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) +#endif // ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) //************************************************************************* /// Removes a value from the front of the forward_list. @@ -870,7 +890,7 @@ namespace etl return iterator(&data_node); } -#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) +#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) //************************************************************************* /// Emplaces a value to the forward_list after the specified position. //************************************************************************* @@ -950,7 +970,7 @@ namespace etl return iterator(p_data_node); } -#endif // ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) +#endif // ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) //************************************************************************* /// Inserts 'n' copies of a value to the forward_list after the specified position. @@ -1332,6 +1352,18 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + iforward_list& operator = (iforward_list&& rhs) + { + move_container(std::move(rhs)); + + return *this; + } +#endif + protected: //************************************************************************* @@ -1381,6 +1413,63 @@ namespace etl start_node.next = nullptr; } + //************************************************************************* + /// Allocate a data_node_t. + //************************************************************************* + data_node_t& allocate_data_node(const_reference value) + { + data_node_t* p_node = p_node_pool->allocate(); + ::new (&(p_node->value)) T(value); + ETL_INCREMENT_DEBUG_COUNT + + return *p_node; + } + +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Allocate a data_node_t. + //************************************************************************* + data_node_t& allocate_data_node(rvalue_reference value) + { + data_node_t* p_node = p_node_pool->allocate(); + ::new (&(p_node->value)) T(std::move(value)); + ETL_INCREMENT_DEBUG_COUNT + + return *p_node; + } +#endif + +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move a forward list + //************************************************************************* + void move_container(iforward_list&& rhs) + { + if (&rhs != this) + { + this->initialise(); + + node_t* p_last_node = &start_node; + + etl::iforward_list::iterator first = rhs.begin(); + etl::iforward_list::iterator last = rhs.end(); + + // Add all of the elements. + while (first != last) + { + ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); + + data_node_t& data_node = this->allocate_data_node(std::move(*first++)); + join(p_last_node, &data_node); + data_node.next = nullptr; + p_last_node = &data_node; + } + + rhs.initialise(); + } + } +#endif + private: //************************************************************************* @@ -1433,18 +1522,6 @@ namespace etl } } - //************************************************************************* - /// Allocate a data_node_t. - //************************************************************************* - data_node_t& allocate_data_node(const T& value) - { - data_node_t* p_node = p_node_pool->allocate(); - ::new (&(p_node->value)) T(value); - ETL_INCREMENT_DEBUG_COUNT - - return *p_node; - } - //************************************************************************* /// Destroy a data_node_t. //************************************************************************* @@ -1521,6 +1598,17 @@ namespace etl this->assign(other.cbegin(), other.cend()); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + forward_list(forward_list&& other) + : etl::iforward_list(node_pool, MAX_SIZE, false) + { + this->move_container(std::move(other)); + } +#endif + //************************************************************************* /// Construct from range. //************************************************************************* @@ -1563,6 +1651,19 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + forward_list& operator = (forward_list&& rhs) + { + + this->move_container(std::move(rhs)); + + return *this; + } +#endif + private: /// The pool of nodes used in the list. @@ -1631,6 +1732,29 @@ namespace etl this->assign(other.cbegin(), other.cend()); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + forward_list(forward_list&& other) + : etl::iforward_list(*other.p_node_pool, other.p_node_pool->max_size(), true) + { + if (this != &other) + { + this->initialise(); + + typename etl::iforward_list::iterator itr = other.begin(); + while (itr != other.end()) + { + this->push_back(std::move(*itr)); + ++itr; + } + + other.initialise(); + } + } +#endif + //************************************************************************* /// Construct from range. //************************************************************************* @@ -1673,6 +1797,18 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + forward_list& operator = (forward_list&& rhs) + { + this->move_container(std::move(rhs)); + + return *this; + } +#endif + //************************************************************************* /// Set the pool instance. //************************************************************************* diff --git a/include/etl/version.h b/include/etl/version.h index 5e652972..0db94648 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -38,8 +38,8 @@ SOFTWARE. ///\ingroup utilities #define ETL_VERSION_MAJOR 14 -#define ETL_VERSION_MINOR 10 -#define ETL_VERSION_PATCH 2 +#define ETL_VERSION_MINOR 11 +#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_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 3644844d..d089d725 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +14.11.0 +Added rvalue reference interfaces to forward_list. + =============================================================================== 14.10.2 Fix for unordered_multimap, unordered_set and unordered_multiset insert and erase bug. diff --git a/test/test_forward_list.cpp b/test/test_forward_list.cpp index c63e8e44..b2f220a6 100644 --- a/test/test_forward_list.cpp +++ b/test/test_forward_list.cpp @@ -48,11 +48,15 @@ namespace typedef TestDataDC ItemDC; typedef TestDataNDC ItemNDC; + typedef TestDataM ItemM; typedef etl::forward_list DataDC; typedef etl::forward_list DataNDC; typedef etl::iforward_list IDataNDC; + typedef etl::forward_list DataM; + typedef etl::iforward_list IDataM; + typedef etl::forward_list DataInt; typedef std::forward_list CompareDataDC; @@ -170,6 +174,98 @@ namespace CHECK(std::equal(data.begin(), data.end(), other_data.begin())); } + //************************************************************************* + TEST(test_move_constructor) + { + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); + + DataM data1; + data1.push_front(std::move(p1)); + data1.push_front(std::move(p2)); + data1.push_front(std::move(p3)); + data1.push_front(std::move(p4)); + + 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()); + + DataM::const_iterator itr = data2.begin(); + + CHECK_EQUAL(4U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(1U, (*itr++).value); + } + + //************************************************************************* + TEST(test_move_assignment) + { + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); + + DataM data1; + data1.push_front(std::move(p1)); + data1.push_front(std::move(p2)); + data1.push_front(std::move(p3)); + data1.push_front(std::move(p4)); + + DataM data2; + data2 = std::move(data1); + + CHECK_EQUAL(0U, data1.size()); + CHECK_EQUAL(4U, data2.size()); + + DataM::const_iterator itr = data2.begin(); + + CHECK_EQUAL(4U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(1U, (*itr++).value); + } + + //************************************************************************* + TEST(test_move_assignment_interface) + { + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); + + DataM data1; + data1.push_front(std::move(p1)); + data1.push_front(std::move(p2)); + data1.push_front(std::move(p3)); + data1.push_front(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(4U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(1U, (*itr++).value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_iterator) { @@ -501,6 +597,35 @@ namespace CHECK(are_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_front_move) + { + ItemM p1(1U); + ItemM p2(2U); + ItemM p3(3U); + ItemM p4(4U); + + DataM 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)); + + DataM::const_iterator itr = data.begin(); + + CHECK_EQUAL(4U, (*itr++).value); + CHECK_EQUAL(3U, (*itr++).value); + CHECK_EQUAL(2U, (*itr++).value); + CHECK_EQUAL(1U, (*itr++).value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_emplace_front) {