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)