Added rvalue reference push_back & insert.

This commit is contained in:
John Wellbelove 2018-12-29 15:36:08 +00:00
parent fa891b9dbc
commit 9266920e2a
3 changed files with 173 additions and 22 deletions

View File

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

View File

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

View File

@ -31,6 +31,7 @@
#include <vector>
#include <array>
#include <algorithm>
#include <memory>
#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<std::unique_ptr<int>, SIZE> data;
std::unique_ptr<int> p1(new int(1));
std::unique_ptr<int> p2(new int(2));
std::unique_ptr<int> p3(new int(3));
std::unique_ptr<int> 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<int, SIZE> 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<std::unique_ptr<int>, SIZE> data;
std::unique_ptr<int> p1(new int(1));
std::unique_ptr<int> p2(new int(2));
std::unique_ptr<int> p3(new int(3));
std::unique_ptr<int> 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)