Merge remote-tracking branch 'origin/hotfix/unique_ptr_unit_tests' into development

This commit is contained in:
John Wellbelove 2020-03-19 17:22:24 +00:00
commit 82b2bfdef0
4 changed files with 477 additions and 113 deletions

View File

@ -36,6 +36,7 @@ SOFTWARE.
#include "type_traits.h"
#include "iterator.h"
#include "utility.h"
#include "nullptr.h"
#include <assert.h>
@ -1232,44 +1233,52 @@ namespace etl
typedef T* pointer;
typedef T& reference;
ETL_CONSTEXPR unique_ptr()
//*********************************
ETL_CONSTEXPR unique_ptr() ETL_NOEXCEPT
: p(nullptr)
{
}
ETL_CONSTEXPR explicit unique_ptr(pointer p_)
//*********************************
ETL_CONSTEXPR explicit unique_ptr(pointer p_) ETL_NOEXCEPT
: p(p_)
{
}
#if ETL_CPP11_SUPPORTED
unique_ptr(unique_ptr&& p_)
//*********************************
unique_ptr(unique_ptr&& p_) ETL_NOEXCEPT
: p(p_.release())
{
}
#endif
//*********************************
~unique_ptr()
{
deleter(p);
}
ETL_CONSTEXPR pointer get() const
//*********************************
ETL_CONSTEXPR pointer get() const ETL_NOEXCEPT
{
return p;
}
TDeleter& get_deleter()
//*********************************
TDeleter& get_deleter() ETL_NOEXCEPT
{
return deleter;
}
const TDeleter& get_deleter() const
//*********************************
const TDeleter& get_deleter() const ETL_NOEXCEPT
{
return deleter;
}
pointer release()
//*********************************
pointer release() ETL_NOEXCEPT
{
pointer value = p;
p = nullptr;
@ -1277,7 +1286,8 @@ namespace etl
return value;
}
void reset(pointer p_ = pointer())
//*********************************
void reset(pointer p_ = pointer()) ETL_NOEXCEPT
{
assert(p_ != p);
@ -1286,25 +1296,31 @@ namespace etl
deleter(value);
}
void swap(unique_ptr& value)
//*********************************
void swap(unique_ptr& value) ETL_NOEXCEPT
{
using ETL_OR_STD::swap;
swap(p, value.p);
}
ETL_CONSTEXPR operator bool() const
//*********************************
ETL_CONSTEXPR operator bool() const ETL_NOEXCEPT
{
return (p != nullptr);
}
unique_ptr& operator =(pointer p_)
//*********************************
unique_ptr& operator =(std::nullptr_t) ETL_NOEXCEPT
{
reset(p_);
reset(nullptr);
return *this;
}
#if ETL_CPP11_SUPPORTED
unique_ptr& operator =(unique_ptr&& p_)
//*********************************
unique_ptr& operator =(unique_ptr&& p_) ETL_NOEXCEPT
{
reset(p_.release());
@ -1312,41 +1328,29 @@ namespace etl
}
#endif
//*********************************
ETL_CONSTEXPR reference operator *() const
{
return *get();
}
ETL_CONSTEXPR pointer operator ->() const
//*********************************
ETL_CONSTEXPR pointer operator ->() const ETL_NOEXCEPT
{
return get();
}
//*********************************
ETL_CONSTEXPR reference operator [](size_t i) const
{
return get()[i];
}
ETL_CONSTEXPR bool operator== (const pointer p_) const
{
return p == p_;
}
ETL_CONSTEXPR bool operator== (const unique_ptr& p_) const
{
return p == p_.p;
}
ETL_CONSTEXPR bool operator< (const unique_ptr& p_) const
{
return p < p_.p;
return p[i];
}
private:
// Deleted.
unique_ptr(const unique_ptr&);
unique_ptr& operator =(const unique_ptr&);
unique_ptr(const unique_ptr&) ETL_DELETE;
unique_ptr& operator =(const unique_ptr&) ETL_DELETE;
TDeleter deleter;
@ -1368,51 +1372,60 @@ namespace etl
typedef T* pointer;
typedef T& reference;
ETL_CONSTEXPR unique_ptr()
//*********************************
ETL_CONSTEXPR unique_ptr() ETL_NOEXCEPT
: p(nullptr)
{
}
ETL_CONSTEXPR explicit unique_ptr(pointer p_)
//*********************************
ETL_CONSTEXPR explicit unique_ptr(pointer p_) ETL_NOEXCEPT
: p(p_)
{
}
#if ETL_CPP11_SUPPORTED
unique_ptr(unique_ptr&& p_)
//*********************************
unique_ptr(unique_ptr&& p_) ETL_NOEXCEPT
: p(p_.release())
{
}
#endif
//*********************************
~unique_ptr()
{
deleter(p);
}
ETL_CONSTEXPR pointer get() const
//*********************************
ETL_CONSTEXPR pointer get() const ETL_NOEXCEPT
{
return p;
}
TDeleter& get_deleter()
//*********************************
TDeleter& get_deleter() ETL_NOEXCEPT
{
return deleter;
}
const TDeleter& get_deleter() const
//*********************************
const TDeleter& get_deleter() const ETL_NOEXCEPT
{
return deleter;
}
pointer release()
//*********************************
pointer release() ETL_NOEXCEPT
{
pointer value = p;
p = nullptr;
return value;
}
void reset(pointer p_)
//*********************************
void reset(pointer p_) ETL_NOEXCEPT
{
assert(p_ != p);
@ -1421,25 +1434,23 @@ namespace etl
delete[] value;
}
void swap(unique_ptr& v)
//*********************************
void swap(unique_ptr& v) ETL_NOEXCEPT
{
using ETL_OR_STD::swap;
swap(p, v.p);
}
ETL_CONSTEXPR operator bool() const
//*********************************
ETL_CONSTEXPR operator bool() const ETL_NOEXCEPT
{
return (p != nullptr);
}
unique_ptr& operator =(pointer p_)
{
reset(p_);
return *this;
}
#if ETL_CPP11_SUPPORTED
unique_ptr& operator =(unique_ptr&& p_)
//*********************************
unique_ptr& operator =(unique_ptr&& p_) ETL_NOEXCEPT
{
reset(p_.release());
@ -1447,41 +1458,29 @@ namespace etl
}
#endif
//*********************************
ETL_CONSTEXPR reference operator *() const
{
return *p;
}
ETL_CONSTEXPR pointer operator ->() const
//*********************************
ETL_CONSTEXPR pointer operator ->() const ETL_NOEXCEPT
{
return p;
}
//*********************************
ETL_CONSTEXPR reference operator [](size_t i) const
{
return p[i];
}
ETL_CONSTEXPR bool operator ==(const pointer p_) const
{
return (p == p_);
}
ETL_CONSTEXPR bool operator ==(const unique_ptr& p_) const
{
return (p == p_.p);
}
ETL_CONSTEXPR bool operator <(const unique_ptr& p_) const
{
return (p < p_.p);
}
private:
// Deleted.
unique_ptr(const unique_ptr&);
unique_ptr& operator =(const unique_ptr&);
unique_ptr(const unique_ptr&) ETL_DELETE;
unique_ptr& operator =(const unique_ptr&) ETL_DELETE;
TDeleter deleter;
@ -1489,6 +1488,113 @@ namespace etl
};
}
//*****************************************************************************
// Global functions for unique_ptr
//*****************************************************************************
template<typename T1, typename D1, typename T2, typename D2>
bool operator ==(const etl::unique_ptr<T1, D1>&lhs, const etl::unique_ptr<T2, D2>& rhs)
{
return lhs.get() == rhs.get();
}
//*********************************
template<typename T1, typename D1, typename T2, typename D2>
bool operator <(const etl::unique_ptr<T1, D1>&lhs, const etl::unique_ptr<T2, D2>& rhs)
{
return reinterpret_cast<char*>(lhs.get()) < reinterpret_cast<char*>(rhs.get());
}
//*********************************
template<typename T1, typename D1, typename T2, typename D2>
bool operator <=(const etl::unique_ptr<T1, D1>&lhs, const etl::unique_ptr<T2, D2>& rhs)
{
return !(rhs < lhs);
}
//*********************************
template<typename T1, typename D1, typename T2, typename D2>
bool operator >(const etl::unique_ptr<T1, D1>&lhs, const etl::unique_ptr<T2, D2>& rhs)
{
return (rhs < lhs);
}
//*********************************
template<typename T1, typename D1, typename T2, typename D2>
bool operator >=(const etl::unique_ptr<T1, D1>&lhs, const etl::unique_ptr<T2, D2>& rhs)
{
return !(lhs < rhs);
}
//*********************************
template <typename T, typename D>
bool operator ==(const etl::unique_ptr<T, D>&lhs, std::nullptr_t)
{
return !lhs;
}
//*********************************
template <typename T, typename D>
bool operator ==(std::nullptr_t, const etl::unique_ptr<T, D>&rhs)
{
return !rhs;
}
//*********************************
template <typename T, typename D>
bool operator <(const etl::unique_ptr<T, D>&lhs, std::nullptr_t)
{
return etl::less<typename etl::unique_ptr<T, D>::pointer>()(lhs.get(), nullptr);
}
//*********************************
template <typename T, typename D>
bool operator <(std::nullptr_t, const etl::unique_ptr<T, D>& rhs)
{
return etl::less<typename etl::unique_ptr<T, D>::pointer>()(nullptr, rhs.get());
}
//*********************************
template <typename T, typename D>
bool operator <=(const etl::unique_ptr<T, D>&lhs, std::nullptr_t)
{
return !(nullptr < lhs);
}
//*********************************
template <typename T, typename D>
bool operator <=(std::nullptr_t, const etl::unique_ptr<T, D>& rhs)
{
return !(rhs < nullptr);
}
//*********************************
template <typename T, typename D>
bool operator >(const etl::unique_ptr<T, D>&lhs, std::nullptr_t)
{
return nullptr < lhs;
}
//*********************************
template <typename T, typename D>
bool operator >(std::nullptr_t, const etl::unique_ptr<T, D>& rhs)
{
return rhs < nullptr;
}
//*********************************
template <typename T, typename D>
bool operator >=(const etl::unique_ptr<T, D>&lhs, std::nullptr_t)
{
return !(lhs < nullptr);
}
//*********************************
template <typename T, typename D>
bool operator >=(std::nullptr_t, const etl::unique_ptr<T, D>& rhs)
{
return !(nullptr < rhs);
}
namespace etl
{
//*****************************************************************************

View File

@ -71,16 +71,21 @@ SOFTWARE.
#define ETL_CONSTEXPR constexpr
#define ETL_CONST_OR_CONSTEXPR constexpr
#define ETL_DELETE = delete
#define ETL_NOEXCEPT noexcept
#define ETL_NOEXCEPT_EXPR(expression) noexcept(expression)
#define ETL_EXPLICIT explicit
#if defined(ETL_EXCEPTIONS_DISABLED)
#define ETL_NOEXCEPT
#define ETL_NOEXCEPT_EXPR(expression)
#else
#define ETL_NOEXCEPT noexcept
#define ETL_NOEXCEPT_EXPR(expression) noexcept(expression)
#endif
#else
#define ETL_CONSTEXPR
#define ETL_CONST_OR_CONSTEXPR const
#define ETL_DELETE
#define ETL_EXPLICIT
#define ETL_NOEXCEPT
#define ETL_NOEXCEPT_EXPR(expression)
#define ETL_EXPLICIT
#endif
// C++14

View File

@ -46,20 +46,20 @@ namespace etl
#if ETL_CPP11_SUPPORTED
//******************************************************************************
template <typename T>
constexpr typename etl::remove_reference<T>::type&& move(T&& t) noexcept
constexpr typename etl::remove_reference<T>::type&& move(T&& t) ETL_NOEXCEPT
{
return static_cast<typename etl::remove_reference<T>::type&&>(t);
}
//******************************************************************************
template <typename T>
constexpr T&& forward(typename etl::remove_reference<T>::type& t) noexcept
constexpr T&& forward(typename etl::remove_reference<T>::type& t) ETL_NOEXCEPT
{
return static_cast<T&&>(t);
}
template <typename T>
constexpr T&& forward(typename etl::remove_reference<T>::type&& t) noexcept
constexpr T&& forward(typename etl::remove_reference<T>::type&& t) ETL_NOEXCEPT
{
return static_cast<T&&>(t);
}
@ -273,7 +273,7 @@ namespace etl
object = new_value;
return old_value;
}
template <typename T, typename U>
T exchange(T& object, const U& new_value)
{

View File

@ -37,6 +37,7 @@ SOFTWARE.
#include <array>
#include <algorithm>
#include <iterator>
#include <numeric>
#include <stdint.h>
#include <vector>
@ -80,6 +81,33 @@ namespace
return nullptr;
}
};
//***********************************
template <typename T>
struct NoDelete
{
NoDelete()
{
}
void operator()(T* p) const
{
}
};
//***********************************
template <typename T>
struct NoDelete<T[]>
{
NoDelete()
{
}
template <class U>
void operator()(U* p) const
{
}
};
}
namespace
@ -344,15 +372,15 @@ namespace
}
is_equal = (output_moveable[0] == moveable_t(0)) &&
(output_moveable[1] == moveable_t(1)) &&
(output_moveable[2] == moveable_t(2)) &&
(output_moveable[3] == moveable_t(3)) &&
(output_moveable[4] == moveable_t(4)) &&
(output_moveable[5] == moveable_t(5)) &&
(output_moveable[6] == moveable_t(6)) &&
(output_moveable[7] == moveable_t(7)) &&
(output_moveable[8] == moveable_t(8)) &&
(output_moveable[9] == moveable_t(9));
(output_moveable[1] == moveable_t(1)) &&
(output_moveable[2] == moveable_t(2)) &&
(output_moveable[3] == moveable_t(3)) &&
(output_moveable[4] == moveable_t(4)) &&
(output_moveable[5] == moveable_t(5)) &&
(output_moveable[6] == moveable_t(6)) &&
(output_moveable[7] == moveable_t(7)) &&
(output_moveable[8] == moveable_t(8)) &&
(output_moveable[9] == moveable_t(9));
CHECK(is_equal);
etl::destroy(p, p + SIZE);
@ -372,15 +400,15 @@ namespace
}
is_equal = (output_moveable[0] == moveable_t(0)) &&
(output_moveable[1] == moveable_t(1)) &&
(output_moveable[2] == moveable_t(2)) &&
(output_moveable[3] == moveable_t(3)) &&
(output_moveable[4] == moveable_t(4)) &&
(output_moveable[5] == moveable_t(5)) &&
(output_moveable[6] == moveable_t(6)) &&
(output_moveable[7] == moveable_t(7)) &&
(output_moveable[8] == moveable_t(8)) &&
(output_moveable[9] == moveable_t(9));
(output_moveable[1] == moveable_t(1)) &&
(output_moveable[2] == moveable_t(2)) &&
(output_moveable[3] == moveable_t(3)) &&
(output_moveable[4] == moveable_t(4)) &&
(output_moveable[5] == moveable_t(5)) &&
(output_moveable[6] == moveable_t(6)) &&
(output_moveable[7] == moveable_t(7)) &&
(output_moveable[8] == moveable_t(8)) &&
(output_moveable[9] == moveable_t(9));
CHECK(is_equal);
CHECK_EQUAL(SIZE, count);
@ -409,15 +437,15 @@ namespace
}
is_equal = (output_moveable[0] == moveable_t(0)) &&
(output_moveable[1] == moveable_t(1)) &&
(output_moveable[2] == moveable_t(2)) &&
(output_moveable[3] == moveable_t(3)) &&
(output_moveable[4] == moveable_t(4)) &&
(output_moveable[5] == moveable_t(5)) &&
(output_moveable[6] == moveable_t(6)) &&
(output_moveable[7] == moveable_t(7)) &&
(output_moveable[8] == moveable_t(8)) &&
(output_moveable[9] == moveable_t(9));
(output_moveable[1] == moveable_t(1)) &&
(output_moveable[2] == moveable_t(2)) &&
(output_moveable[3] == moveable_t(3)) &&
(output_moveable[4] == moveable_t(4)) &&
(output_moveable[5] == moveable_t(5)) &&
(output_moveable[6] == moveable_t(6)) &&
(output_moveable[7] == moveable_t(7)) &&
(output_moveable[8] == moveable_t(8)) &&
(output_moveable[9] == moveable_t(9));
CHECK(is_equal);
etl::destroy(p, p + SIZE);
@ -437,15 +465,15 @@ namespace
}
is_equal = (output_moveable[0] == moveable_t(0)) &&
(output_moveable[1] == moveable_t(1)) &&
(output_moveable[2] == moveable_t(2)) &&
(output_moveable[3] == moveable_t(3)) &&
(output_moveable[4] == moveable_t(4)) &&
(output_moveable[5] == moveable_t(5)) &&
(output_moveable[6] == moveable_t(6)) &&
(output_moveable[7] == moveable_t(7)) &&
(output_moveable[8] == moveable_t(8)) &&
(output_moveable[9] == moveable_t(9));
(output_moveable[1] == moveable_t(1)) &&
(output_moveable[2] == moveable_t(2)) &&
(output_moveable[3] == moveable_t(3)) &&
(output_moveable[4] == moveable_t(4)) &&
(output_moveable[5] == moveable_t(5)) &&
(output_moveable[6] == moveable_t(6)) &&
(output_moveable[7] == moveable_t(7)) &&
(output_moveable[8] == moveable_t(8)) &&
(output_moveable[9] == moveable_t(9));
CHECK(is_equal);
CHECK_EQUAL(SIZE, count);
@ -678,7 +706,7 @@ namespace
etl::memory_clear(data);
CHECK_EQUAL(0x00000000, data.d1);
CHECK_EQUAL(0x00, data.d2);
CHECK_EQUAL(0x00, data.d2);
}
//*************************************************************************
@ -741,7 +769,7 @@ namespace
etl::memory_set(data, 0x5A);
CHECK_EQUAL(0x5A5A5A5A, data.d1);
CHECK_EQUAL(0x5A, data.d2);
CHECK_EQUAL(0x5A, data.d2);
}
//*************************************************************************
@ -789,5 +817,230 @@ namespace
CHECK_EQUAL(0x5A5A5A5A, data[2].d1);
CHECK_EQUAL(0x5A, data[2].d2);
}
//*************************************************************************
TEST(test_unique_ptr_default_construction)
{
etl::unique_ptr<int> up;
CHECK(up.get() == nullptr);
CHECK(!bool(up));
}
//*************************************************************************
TEST(test_unique_ptr_from_pointer_construction)
{
etl::unique_ptr<int> up(new int(1));
CHECK(up.get() != nullptr);
CHECK(bool(up));
CHECK_EQUAL(1, *up);
}
//*************************************************************************
TEST(test_unique_ptr_move_construction)
{
etl::unique_ptr<int> up1(new int(1));
etl::unique_ptr<int> up2(std::move(up1));
CHECK(up1.get() == nullptr);
CHECK(!bool(up1));
CHECK(up2.get() != nullptr);
CHECK(bool(up2));
CHECK_EQUAL(1, *up2);
}
//*************************************************************************
TEST(test_unique_ptr_release)
{
etl::unique_ptr<int> up(new int);
CHECK(up.release() != nullptr);
CHECK(!bool(up));
}
//*************************************************************************
TEST(test_unique_ptr_reset)
{
etl::unique_ptr<int> up(new int(1));
int* p = new int(2);
CHECK_EQUAL(1, *up);
up.reset(p);
CHECK_EQUAL(2, *up);
}
//*************************************************************************
TEST(test_unique_ptr_swap)
{
etl::unique_ptr<int> up1(new int(1));
etl::unique_ptr<int> up2(new int(2));
up1.swap(up2);
CHECK_EQUAL(2, *up1);
CHECK_EQUAL(1, *up2);
}
//*************************************************************************
TEST(test_unique_ptr_from_nullptr_assignment)
{
etl::unique_ptr<int> up(new int);
int* p = new int(1);
up = nullptr;
CHECK(up.get() == nullptr);
CHECK(!bool(up));
}
//*************************************************************************
TEST(test_unique_ptr_move_assignment)
{
etl::unique_ptr<int> up1(new int(1));
etl::unique_ptr<int> up2(new int(2));
up1 = std::move(up2);
CHECK(!bool(up2));
CHECK_EQUAL(2, *up1);
}
//*************************************************************************
TEST(test_unique_ptr_comparison_tests)
{
int* p1 = (int*)1U;
int* p2 = (int*)2U;
etl::unique_ptr<int, NoDelete<int>> up1(p1);
etl::unique_ptr<int, NoDelete<int>> up2(p1);
etl::unique_ptr<int, NoDelete<int>> up3(p2);
CHECK(up1 == up2);
CHECK(!(up1 == up3));
CHECK(!(up1 < up2));
CHECK(up1 < up3);
CHECK(!(up3 <= up1));
CHECK(up1 <= up2);
CHECK(up1 <= up3);
CHECK(!(up1 > up2));
CHECK(up3 > up1);
CHECK(!(up1 >= up3));
CHECK(up2 >= up1);
CHECK(up3 >= up1);
}
//*************************************************************************
TEST(test_unique_ptr_from_array_pointer_construction)
{
etl::unique_ptr<int> up(new int[4]);
std::iota(&up[0], &up[4], 0);
CHECK(up.get() != nullptr);
CHECK(bool(up));
CHECK_EQUAL(0, up[0]);
CHECK_EQUAL(1, up[1]);
CHECK_EQUAL(2, up[2]);
CHECK_EQUAL(3, up[3]);
}
//*************************************************************************
TEST(test_unique_ptr_move_array_construction)
{
etl::unique_ptr<int> up1(new int[4]);
std::iota(&up1[0], &up1[4], 0);
etl::unique_ptr<int> up2(std::move(up1));
CHECK(up1.get() == nullptr);
CHECK(!bool(up1));
CHECK(up2.get() != nullptr);
CHECK(bool(up2));
CHECK_EQUAL(0, up2[0]);
CHECK_EQUAL(1, up2[1]);
CHECK_EQUAL(2, up2[2]);
CHECK_EQUAL(3, up2[3]);
}
//*************************************************************************
TEST(test_unique_ptr_array_release)
{
etl::unique_ptr<int> up(new int[4]);
std::iota(&up[0], &up[4], 0);
CHECK(up.release() != nullptr);
CHECK(!bool(up));
}
//*************************************************************************
TEST(test_unique_ptr_array_reset)
{
etl::unique_ptr<int> up(new int[4]);
std::iota(&up[0], &up[4], 0);
int* p = new int[4];
std::iota(p, p + 4, 4);
CHECK_EQUAL(0, up[0]);
CHECK_EQUAL(1, up[1]);
CHECK_EQUAL(2, up[2]);
CHECK_EQUAL(3, up[3]);
up.reset(p);
CHECK_EQUAL(4, up[0]);
CHECK_EQUAL(5, up[1]);
CHECK_EQUAL(6, up[2]);
CHECK_EQUAL(7, up[3]);
}
//*************************************************************************
TEST(test_unique_ptr_array_swap)
{
etl::unique_ptr<int> up1(new int[4]);
std::iota(&up1[0], &up1[4], 0);
etl::unique_ptr<int> up2(new int[4]);
std::iota(&up2[0], &up2[4], 4);
up1.swap(up2);
CHECK_EQUAL(4, up1[0]);
CHECK_EQUAL(5, up1[1]);
CHECK_EQUAL(6, up1[2]);
CHECK_EQUAL(7, up1[3]);
CHECK_EQUAL(0, up2[0]);
CHECK_EQUAL(1, up2[1]);
CHECK_EQUAL(2, up2[2]);
CHECK_EQUAL(3, up2[3]);
}
//*************************************************************************
TEST(test_unique_ptr_array_from_nullptr_assignment)
{
etl::unique_ptr<int> up(new int[4]);
int* p = new int[4];
up = nullptr;
CHECK(up.get() == nullptr);
CHECK(!bool(up));
}
//*************************************************************************
TEST(test_unique_ptr_array_move_assignment)
{
etl::unique_ptr<int> up1(new int[4]);
std::iota(&up1[0], &up1[4], 0);
etl::unique_ptr<int> up2(new int[4]);
std::iota(&up2[0], &up2[4], 4);
up1 = std::move(up2);
CHECK(!bool(up2));
CHECK_EQUAL(4, up1[0]);
CHECK_EQUAL(5, up1[1]);
CHECK_EQUAL(6, up1[2]);
CHECK_EQUAL(7, up1[3]);
}
};
}