Fix etl::unique_ptr::swap() for deleters (#1482)

* Fix etl::unique_ptr::swap() for deleters

Fixes https://github.com/ETLCPP/etl/issues/1481

* Fix etl::deque iterator swap()

Swap all members, not just the index.
This commit is contained in:
Roland Reichwein 2026-06-27 17:00:04 +02:00 committed by GitHub
parent e6a7642121
commit 0663fc7078
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 142 additions and 0 deletions

View File

@ -457,6 +457,8 @@ namespace etl
using ETL_OR_STD::swap; // Allow ADL
swap(index, other.index);
swap(p_deque, other.p_deque);
swap(p_buffer, other.p_buffer);
}
private:
@ -703,6 +705,8 @@ namespace etl
void swap(const_iterator& other)
{
ETL_OR_STD::swap(index, other.index);
ETL_OR_STD::swap(p_deque, other.p_deque);
ETL_OR_STD::swap(p_buffer, other.p_buffer);
}
private:

View File

@ -2085,6 +2085,7 @@ namespace etl
using ETL_OR_STD::swap;
swap(p, value.p);
swap(deleter, value.deleter);
}
//*********************************
@ -2292,6 +2293,7 @@ namespace etl
using ETL_OR_STD::swap;
swap(p, v.p);
swap(deleter, v.deleter);
}
//*********************************

View File

@ -632,6 +632,42 @@ namespace
CHECK(third >= first);
}
//*************************************************************************
// The member swap() must exchange the complete iterator state (index,
// owning deque and buffer).
TEST(test_iterator_swap_different_deques)
{
DataInt data1 = {1, 2, 3, 4, 5};
DataInt data2 = {10, 20, 30, 40, 50};
DataInt::iterator itr1 = data1.begin() + 1; // -> 2
DataInt::iterator itr2 = data2.begin() + 3; // -> 40
itr1.swap(itr2);
CHECK_EQUAL(40, *itr1);
CHECK_EQUAL(2, *itr2);
CHECK(&itr1.container() == &data2);
CHECK(&itr2.container() == &data1);
}
//*************************************************************************
TEST(test_const_iterator_swap_different_deques)
{
DataInt data1 = {1, 2, 3, 4, 5};
DataInt data2 = {10, 20, 30, 40, 50};
DataInt::const_iterator itr1 = data1.begin() + 1; // -> 2
DataInt::const_iterator itr2 = data2.begin() + 3; // -> 40
itr1.swap(itr2);
CHECK_EQUAL(40, *itr1);
CHECK_EQUAL(2, *itr2);
CHECK(&itr1.container() == &data2);
CHECK(&itr2.container() == &data1);
}
//*************************************************************************
TEST(test_iterator_comparison_rollover_left)
{

View File

@ -923,6 +923,56 @@ namespace
CHECK_EQUAL(1, *up2);
}
//*************************************************************************
TEST(test_unique_ptr_swap_deleters)
{
struct Deleter
{
char id;
explicit Deleter(const char id_)
: id(id_)
{
}
Deleter(const Deleter&) = delete;
Deleter& operator=(const Deleter&) = delete;
Deleter(Deleter&& other) noexcept
: id(other.id)
{
other.id = ' ';
}
Deleter& operator=(Deleter&& other) noexcept
{
if (&other != this)
{
id = other.id;
other.id = ' ';
}
return *this;
}
~Deleter() = default;
void operator()(int*) const {}
};
int a_obj = 1;
int b_obj = 2;
etl::unique_ptr<int, Deleter> up1(&a_obj, Deleter('A'));
etl::unique_ptr<int, Deleter> up2(&b_obj, Deleter('B'));
up1.swap(up2);
CHECK_EQUAL(2, *up1);
CHECK_EQUAL('B', up1.get_deleter().id);
CHECK_EQUAL(1, *up2);
CHECK_EQUAL('A', up2.get_deleter().id);
}
//*************************************************************************
TEST(test_unique_ptr_from_nullptr_assignment)
{
@ -1067,6 +1117,56 @@ namespace
CHECK_EQUAL(3, up2[3]);
}
//*************************************************************************
TEST(test_unique_ptr_array_swap_deleters)
{
struct Deleter
{
char id;
explicit Deleter(const char id_)
: id(id_)
{
}
Deleter(const Deleter&) = delete;
Deleter& operator=(const Deleter&) = delete;
Deleter(Deleter&& other) noexcept
: id(other.id)
{
other.id = ' ';
}
Deleter& operator=(Deleter&& other) noexcept
{
if (&other != this)
{
id = other.id;
other.id = ' ';
}
return *this;
}
~Deleter() = default;
void operator()(int*) const {}
};
int a_obj = 1;
int b_obj = 2;
etl::unique_ptr<int[], Deleter> up1(&a_obj, Deleter('A'));
etl::unique_ptr<int[], Deleter> up2(&b_obj, Deleter('B'));
up1.swap(up2);
CHECK_EQUAL(2, up1[0]);
CHECK_EQUAL('B', up1.get_deleter().id);
CHECK_EQUAL(1, up2[0]);
CHECK_EQUAL('A', up2.get_deleter().id);
}
//*************************************************************************
TEST(test_unique_ptr_array_from_nullptr_assignment)
{