Fix for 1405: etl::exchange doesn't work with unique_ptr (#1477)

* Separate bit order and endianness in bit_stream.h (#1495)

* Factor out ranges tests from test_algorithm.cpp to test_algorithm_ranges.cpp (#1497)

* Fix exchange to use forwarding reference (U&&) and move

- etl::exchange was using the copy constructor. Changed for etl::move.
- The assignment to the new object is now done with forward.
- Added a test with unique_ptr.

---------

Co-authored-by: Roland Reichwein <Roland.Reichwein@bmw.de>
Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
This commit is contained in:
vcoselev 2026-07-11 12:05:39 +01:00 committed by GitHub
parent 2ed9019df0
commit 4bf6ed6ce8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 6 deletions

View File

@ -490,6 +490,7 @@ namespace etl
};
#if ETL_NOT_USING_STL || ETL_CPP14_NOT_SUPPORTED
#if ETL_CPP11_NOT_SUPPORTED
//***************************************************************************
/// exchange (const)
//***************************************************************************
@ -500,7 +501,6 @@ namespace etl
object = new_value;
return old_value;
}
template <typename T, typename U>
T exchange(T& object, const U& new_value)
{
@ -510,14 +510,28 @@ namespace etl
}
#else
//***************************************************************************
/// exchange (const)
/// exchange
//***************************************************************************
template <typename T, typename U = T>
T exchange(T& object, const U& new_value)
ETL_CONSTEXPR14 T exchange(T& object, U&& new_value)
ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible<T>::value && etl::is_nothrow_assignable<T&, U>::value))
{
return std::exchange(object, new_value);
T old_value = etl::move(object);
object = etl::forward<U>(new_value);
return old_value;
}
#endif
#endif // ETL_CPP11_NOT_SUPPORTED
#else
//***************************************************************************
/// exchange
//***************************************************************************
template <typename T, typename U = T>
ETL_CONSTEXPR14 T exchange(T& object, U&& new_value)
ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible<T>::value && etl::is_nothrow_assignable<T&, U>::value))
{
return std::exchange(object, etl::forward<U>(new_value));
}
#endif // ETL_NOT_USING_STL || ETL_CPP14_NOT_SUPPORTED
//***************************************************************************
/// as_const

View File

@ -28,6 +28,7 @@ SOFTWARE.
#include "unit_test_framework.h"
#include "etl/memory.h"
#include "etl/utility.h"
#include <algorithm>
@ -315,6 +316,32 @@ namespace
CHECK_EQUAL(1, c);
}
//*************************************************************************
TEST(test_exchange_unique_ptr)
{
etl::unique_ptr<int> p1(new int(1));
etl::unique_ptr<int> p2 = etl::exchange(p1, nullptr);
CHECK_FALSE(p1);
CHECK_TRUE(p2);
CHECK_EQUAL(*p2, 1);
}
//*************************************************************************
TEST(test_exchange_unique_ptr_move_in)
{
etl::unique_ptr<int> a(new int(10));
etl::unique_ptr<int> b(new int(20));
etl::unique_ptr<int> old = etl::exchange(a, etl::move(b));
CHECK_TRUE(old);
CHECK_EQUAL(*old, 10);
CHECK_TRUE(a);
CHECK_EQUAL(*a, 20);
CHECK_FALSE(b);
}
//*************************************************************************
TEST(test_as_const)
{