Merge remote-tracking branch 'origin/feature/rvalue-references' into development

This commit is contained in:
John Wellbelove 2018-12-16 19:00:10 +00:00
commit 3b2ef51e54
7 changed files with 368 additions and 17 deletions

View File

@ -38,6 +38,7 @@ SOFTWARE.
#include "stl/algorithm.h"
#include "stl/iterator.h"
#include "stl/utility.h"
#include "container.h"
#include "alignment.h"
@ -916,6 +917,60 @@ namespace etl
return position;
}
#if ETL_CPP11_SUPPORTED
//*************************************************************************
/// Inserts data into the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is full.
///\param insert_position>The insert position.
///\param value>The value to insert.
//*************************************************************************
iterator insert(const_iterator insert_position, value_type&& value)
{
iterator position(insert_position.index, *this, p_buffer);
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
if (insert_position == begin())
{
create_element_front(std::move(value));
position = _begin;
}
else if (insert_position == end())
{
create_element_back(std::move(value));
position = _end - 1;
}
else
{
// Are we closer to the front?
if (std::distance(_begin, position) < std::distance(position, _end - 1))
{
// Construct the _begin.
create_element_front(std::move(*_begin));
// Move the values.
std::move(_begin + 1, position, _begin);
// Write the new value.
*--position = std::move(value);
}
else
{
// Construct the _end.
create_element_back(std::move(*(_end - 1)));
// Move the values.
std::move_backward(position, _end - 2, _end - 1);
// Write the new value.
*position = std::move(value);
}
}
return position;
}
#endif
//*************************************************************************
/// Emplaces data into the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is full.
@ -1577,6 +1632,21 @@ namespace etl
create_element_back(item);
}
#if ETL_CPP11_SUPPORTED
//*************************************************************************
/// Adds an item to the back of the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full.
///\param item The item to push to the deque.
//*************************************************************************
void push_back(T&& item)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
#endif
create_element_back(std::move(item));
}
#endif
#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL)
//*************************************************************************
/// Emplaces an item to the back of the deque.
@ -1690,6 +1760,21 @@ namespace etl
create_element_front(item);
}
#if ETL_CPP11_SUPPORTED
//*************************************************************************
/// Adds an item to the front of the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full.
///\param item The item to push to the deque.
//*************************************************************************
void push_front(T&& item)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
#endif
create_element_front(std::move(item));
}
#endif
#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL)
//*************************************************************************
/// Emplaces an item to the front of the deque.
@ -1999,6 +2084,30 @@ namespace etl
ETL_INCREMENT_DEBUG_COUNT
}
#if ETL_CPP11_SUPPORTED
//*********************************************************************
/// Create a new element with a default value at the front.
//*********************************************************************
void create_element_front(T&& value)
{
--_begin;
::new (&(*_begin)) T(std::move(value));
++current_size;
ETL_INCREMENT_DEBUG_COUNT
}
//*********************************************************************
/// Create a new element with a value at the back
//*********************************************************************
void create_element_back(T&& value)
{
::new (&(*_end)) T(std::move(value));
++_end;
++current_size;
ETL_INCREMENT_DEBUG_COUNT
}
#endif
//*********************************************************************
/// Destroy an element at the front.
//*********************************************************************
@ -2129,6 +2238,29 @@ namespace etl
}
}
#if ETL_CPP11_SUPPORTED
//*************************************************************************
/// Move constructor.
//*************************************************************************
deque(deque&& other)
: etl::ideque<T>(reinterpret_cast<T*>(&buffer[0]), MAX_SIZE, BUFFER_SIZE)
{
if (this != &other)
{
this->initialise();
typename etl::ideque<T>::iterator itr = other.begin();
while (itr != other.end())
{
this->push_back(std::move(*itr));
++itr;
}
other.initialise();
}
}
#endif
//*************************************************************************
/// Assigns data to the deque.
//*************************************************************************
@ -2172,6 +2304,29 @@ namespace etl
return *this;
}
#if ETL_CPP11_SUPPORTED
//*************************************************************************
/// Move assignment operator.
//*************************************************************************
deque& operator =(deque&& rhs)
{
if (&rhs != this)
{
this->clear();
typename etl::ideque<T>::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.
//*************************************************************************

View File

@ -162,6 +162,32 @@ namespace std
return de;
}
//***************************************************************************
// move
template <typename TIterator1, typename TIterator2>
TIterator2 move(TIterator1 sb, TIterator1 se, TIterator2 db)
{
while (sb != se)
{
*db++ = std::move(*sb++);
}
return db;
}
//***************************************************************************
// move_backward
template <typename TIterator1, typename TIterator2>
TIterator2 move_backward(TIterator1 sb, TIterator1 se, TIterator2 de)
{
while (sb != se)
{
*(--de) = std::move(*(--se));
}
return de;
}
//***************************************************************************
// lower_bound
template<typename TIterator, typename TValue, typename TCompare>

View File

@ -1,4 +1,4 @@
///\file
///\file
/******************************************************************************
The MIT License(MIT)
@ -32,6 +32,7 @@ SOFTWARE.
#define ETL_STL_ALTERNATE_UTILITY_INCLUDED
#include "../../platform.h"
#include "../../type_traits.h"
#if defined(ETL_IN_UNIT_TEST)
#if !defined(ETLSTD)
@ -48,7 +49,7 @@ SOFTWARE.
#if !defined(ETL_COMPILER_ARM6)
//******************************************************************************
template <typename T1, typename T2>
struct pair
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
@ -57,27 +58,27 @@ SOFTWARE.
T2 second;
pair()
: first(T1()),
second(T2())
: first(T1()),
second(T2())
{
}
pair(const T1& a, const T2& b)
: first(a),
pair(const T1& a, const T2& b)
: first(a),
second(b)
{
}
template <typename U1, typename U2>
pair(const pair<U1, U2>& other)
: first(other.first),
second(other.second)
pair(const pair<U1, U2>& other)
: first(other.first),
second(other.second)
{
}
pair(const pair<T1, T2>& other)
: first(other.first),
second(other.second)
pair(const pair<T1, T2>& other)
: first(other.first),
second(other.second)
{
}
@ -99,7 +100,7 @@ SOFTWARE.
return pair<T1, T2>(a, b);
}
#if !defined(ETL_COMPILER_ARM6)
#if !defined(ETL_COMPILER_ARM6)
//******************************************************************************
template <typename T1, typename T2>
inline void swap(pair<T1, T2>& a, pair<T1, T2>& b)
@ -121,7 +122,7 @@ SOFTWARE.
}
template <typename T1, typename T2>
inline bool operator <(const pair<T1, T2>& a, const pair<T1, T2>& b)
inline bool operator <(const pair<T1, T2>& a, const pair<T1, T2>& b)
{
return (a.first < b.first) ||
(!(b.first < a.first) && (a.second < b.second));
@ -145,6 +146,14 @@ SOFTWARE.
return !(a < b);
}
#endif
#if ETL_CPP11_SUPPORTED
template <typename T>
constexpr typename etl::remove_reference<T>::type&& move(T&& t) noexcept
{
return static_cast<typename etl::remove_reference<T>::type&&>(t);
}
#endif
}
#endif

View File

@ -38,7 +38,7 @@ SOFTWARE.
///\ingroup utilities
#define ETL_VERSION_MAJOR 14
#define ETL_VERSION_MINOR 4
#define ETL_VERSION_MINOR 5
#define ETL_VERSION_PATCH 0
#define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) ETL_STRINGIFY(ETL_VERSION_MINOR) ETL_STRINGIFY(ETL_VERSION_PATCH)

View File

@ -1,3 +1,8 @@
===============================================================================
14.5.0
Added move algorithms and utility to 'alternate' STL.
Added rvalue reference API to etl::deque.
===============================================================================
14.4.0
Added C++03/C++11 emplace for deque, priority_queue, queues, stack, variant & vector.

View File

@ -39,6 +39,7 @@ SOFTWARE.
#include <iostream>
#include <numeric>
#include <cstring>
#include <memory>
namespace
{
@ -88,7 +89,6 @@ namespace
std::vector<int> int_data1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
std::vector<int> int_data2 = { 15, 16, 17, 18 };
//*************************************************************************
TEST(test_constructor)
{
@ -145,7 +145,7 @@ namespace
CHECK_EQUAL(compare_data.size(), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin()));
}
//*************************************************************************
TEST(test_copy_constructor)
{
@ -1688,5 +1688,66 @@ namespace
CHECK(!is_equal);
}
//*************************************************************************
TEST(test_move)
{
const size_t SIZE = 10U;
typedef etl::deque<std::unique_ptr<unsigned>, SIZE> Data;
Data data1;
std::unique_ptr<uint32_t> p1(new uint32_t(1U));
std::unique_ptr<uint32_t> p2(new uint32_t(2U));
std::unique_ptr<uint32_t> p3(new uint32_t(3U));
std::unique_ptr<uint32_t> p4(new uint32_t(4U));
std::unique_ptr<uint32_t> p5(new uint32_t(5U));
// Move items to data1.
data1.push_front(std::move(p1));
data1.push_back(std::move(p2));
data1.insert(data1.begin(), std::move(p3));
data1.insert(data1.begin() + 1, std::move(p4));
data1.insert(data1.end(), std::move(p5));
const size_t ACTUAL_SIZE = data1.size();
CHECK(!bool(p1));
CHECK(!bool(p2));
CHECK(!bool(p3));
CHECK(!bool(p4));
CHECK(!bool(p5));
CHECK_EQUAL(3U, *(*(data1.begin() + 0)));
CHECK_EQUAL(4U, *(*(data1.begin() + 1)));
CHECK_EQUAL(1U, *(*(data1.begin() + 2)));
CHECK_EQUAL(2U, *(*(data1.begin() + 3)));
CHECK_EQUAL(5U, *(*(data1.begin() + 4)));
// Move constructor.
Data data2(std::move(data1));
CHECK_EQUAL(3U, *(*(data2.begin() + 0)));
CHECK_EQUAL(4U, *(*(data2.begin() + 1)));
CHECK_EQUAL(1U, *(*(data2.begin() + 2)));
CHECK_EQUAL(2U, *(*(data2.begin() + 3)));
CHECK_EQUAL(5U, *(*(data2.begin() + 4)));
CHECK(data1.empty());
CHECK_EQUAL(ACTUAL_SIZE, data2.size());
// Move assignment.
Data data3;
data3 = std::move(data2);
CHECK_EQUAL(3U, *(*(data3.begin() + 0)));
CHECK_EQUAL(4U, *(*(data3.begin() + 1)));
CHECK_EQUAL(1U, *(*(data3.begin() + 2)));
CHECK_EQUAL(2U, *(*(data3.begin() + 3)));
CHECK_EQUAL(5U, *(*(data3.begin() + 4)));
CHECK(data2.empty());
CHECK_EQUAL(ACTUAL_SIZE, data3.size());
}
};
}

View File

@ -36,6 +36,7 @@ SOFTWARE.
#include <algorithm>
#include <vector>
#include <list>
#include <memory>
#include "no_stl_test_iterators.h"
@ -646,5 +647,99 @@ namespace
bool isEqual = std::equal(std::begin(dataD1), std::end(dataD1), std::begin(dataD2));
CHECK(isEqual);
}
//*************************************************************************
TEST(move)
{
typedef std::vector<std::unique_ptr<unsigned>> Data;
Data data1;
// Create some data.
std::unique_ptr<uint32_t> p1(new uint32_t(1U));
std::unique_ptr<uint32_t> p2(new uint32_t(2U));
std::unique_ptr<uint32_t> p3(new uint32_t(3U));
std::unique_ptr<uint32_t> p4(new uint32_t(4U));
std::unique_ptr<uint32_t> p5(new uint32_t(5U));
// Fill 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));
data1.push_back(std::move(p5));
Data data2;
// Move to data2.
etlstd::move(data1.begin(), data1.end(), std::back_inserter(data2));
// Old data now empty.
CHECK(!bool(p1));
CHECK(!bool(p2));
CHECK(!bool(p3));
CHECK(!bool(p4));
CHECK(!bool(p5));
CHECK_EQUAL(1U, *(data2[0]));
CHECK_EQUAL(2U, *(data2[1]));
CHECK_EQUAL(3U, *(data2[2]));
CHECK_EQUAL(4U, *(data2[3]));
CHECK_EQUAL(5U, *(data2[4]));
}
//*************************************************************************
TEST(move_backward)
{
typedef std::vector<std::unique_ptr<unsigned>> Data;
Data data1;
// Create some data.
std::unique_ptr<uint32_t> p1(new uint32_t(1U));
std::unique_ptr<uint32_t> p2(new uint32_t(2U));
std::unique_ptr<uint32_t> p3(new uint32_t(3U));
std::unique_ptr<uint32_t> p4(new uint32_t(4U));
std::unique_ptr<uint32_t> p5(new uint32_t(5U));
// Fill 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));
data1.push_back(std::move(p5));
Data data2;
// Create some data.
std::unique_ptr<uint32_t> p6(new uint32_t(6U));
std::unique_ptr<uint32_t> p7(new uint32_t(7U));
std::unique_ptr<uint32_t> p8(new uint32_t(8U));
std::unique_ptr<uint32_t> p9(new uint32_t(9U));
std::unique_ptr<uint32_t> p10(new uint32_t(10U));
// Fill data2.
data2.push_back(std::move(p6));
data2.push_back(std::move(p7));
data2.push_back(std::move(p8));
data2.push_back(std::move(p9));
data2.push_back(std::move(p10));
// Overwrite data2 with data1.
etlstd::move_backward(data1.begin(), data1.end(), data2.end());
// Old data now empty.
CHECK(!bool(p1));
CHECK(!bool(p2));
CHECK(!bool(p3));
CHECK(!bool(p4));
CHECK(!bool(p5));
CHECK_EQUAL(1U, *(data2[0]));
CHECK_EQUAL(2U, *(data2[1]));
CHECK_EQUAL(3U, *(data2[2]));
CHECK_EQUAL(4U, *(data2[3]));
CHECK_EQUAL(5U, *(data2[4]));
}
};
}