From ad9bda90bca0ce14a7ffd5f247ed8162d93a112f Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 28 Jan 2025 11:15:44 +0000 Subject: [PATCH] Added etl::to_address --- include/etl/memory.h | 63 +++++++++++++++++++++++++++++++++++++------- test/test_memory.cpp | 18 ++++++++++++- 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/include/etl/memory.h b/include/etl/memory.h index 14964b85..10b5cef6 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -54,6 +54,49 @@ SOFTWARE. namespace etl { +#if ETL_USING_STL && ETL_USING_CPP20 + //***************************************************************************** + /// Obtain the address represented by p without forming a reference to the object pointed to by p. + /// Defined when using the STL and C++20 + //***************************************************************************** + template + constexpr auto to_address(const TPtr& p) noexcept + { + return std::to_address(p); + } + + //***************************************************************************** + /// Obtain the address represented by p without forming a reference to the object pointed to by p. + /// Defined when using the STL and C++20 + //***************************************************************************** + template + constexpr T* to_address(T* p) noexcept + { + return std::to_address(p); + } +#else + //***************************************************************************** + /// Obtain the address represented by p without forming a reference to the object pointed to by p. + /// Defined when not using the STL or C++20 + //***************************************************************************** + template + ETL_CONSTEXPR T* to_address(T* p) + { + return p; + } + + //***************************************************************************** + /// Obtain the address represented by itr without forming a reference to the object pointed to by itr. + /// Requires that the iterator defines operator->() + /// Defined when not using the STL or C++20 + //***************************************************************************** + template + ETL_CONSTEXPR typename Iterator::pointer to_address(const Iterator& itr) + { + return itr.operator->(); + } +#endif + #if ETL_USING_STL //***************************************************************************** /// Fills uninitialised memory range with a value. @@ -112,7 +155,7 @@ namespace etl while (o_begin != o_end) { - ::new (static_cast(etl::addressof(*o_begin))) value_type(value); + ::new (static_cast(etl::to_address(o_begin))) value_type(value); ++o_begin; } @@ -259,7 +302,7 @@ namespace etl while (i_begin != i_end) { - ::new (static_cast(etl::addressof(*o_end))) value_type(*i_begin); + ::new (static_cast(etl::to_address(o_end))) value_type(*i_begin); ++i_begin; ++o_end; } @@ -407,7 +450,7 @@ namespace etl while (i_begin != i_end) { - ::new (static_cast(etl::addressof(*o_end))) value_type(etl::move(*i_begin)); + ::new (static_cast(etl::to_address(o_end))) value_type(etl::move(*i_begin)); ++i_begin; ++o_end; } @@ -532,7 +575,7 @@ namespace etl while (n-- != 0) { - ::new (static_cast(etl::addressof(*o_end))) value_type(etl::move(*i_begin)); + ::new (static_cast(etl::to_address(o_end))) value_type(etl::move(*i_begin)); ++i_begin; ++o_end; } @@ -665,7 +708,7 @@ namespace etl while (o_begin != o_end) { - ::new (static_cast(etl::addressof(*o_begin))) value_type; + ::new (static_cast(etl::to_address(o_begin))) value_type; ++o_begin; } } @@ -844,7 +887,7 @@ namespace etl while (o_begin != o_end) { - ::new (static_cast(etl::addressof(*o_begin))) value_type(); + ::new (static_cast(etl::to_address(o_begin))) value_type(); ++o_begin; } } @@ -1095,7 +1138,7 @@ namespace etl { while (i_begin != i_end) { - etl::destroy_at(etl::addressof(*i_begin)); + etl::destroy_at(etl::to_address(i_begin)); ++i_begin; } } @@ -1127,7 +1170,7 @@ namespace etl while (i_begin != i_end) { - etl::destroy_at(etl::addressof(*i_begin)); + etl::destroy_at(etl::to_address(i_begin)); ++i_begin; } } @@ -1182,7 +1225,7 @@ namespace etl { while (n > 0) { - etl::destroy_at(etl::addressof(*i_begin)); + etl::destroy_at(etl::to_address(i_begin)); ++i_begin; --n; } @@ -1218,7 +1261,7 @@ namespace etl while (n > 0) { - etl::destroy_at(etl::addressof(*i_begin)); + etl::destroy_at(etl::to_address(i_begin)); ++i_begin; --n; } diff --git a/test/test_memory.cpp b/test/test_memory.cpp index 13cd14e6..9546afef 100644 --- a/test/test_memory.cpp +++ b/test/test_memory.cpp @@ -29,6 +29,7 @@ SOFTWARE. #include "unit_test_framework.h" #include "etl/memory.h" +#include "etl/list.h" #include "etl/debug_count.h" #include "data.h" @@ -1450,7 +1451,7 @@ namespace CHECK(ptr.get() == ETL_NULLPTR); } - //************************************************************************* + struct Flags { Flags() @@ -1623,5 +1624,20 @@ namespace CHECK_THROW(etl::destroy_object_at(pbuffer1), etl::alignment_error); } + + //************************************************************************* + TEST(test_to_address) + { + int i; + int* pi = &i; + + etl::list container = { 1, 2, 3, 4 }; + etl::list::iterator itr = container.begin(); + std::advance(itr, 2); + int* plist_item = &*itr; + + CHECK_EQUAL(&i, etl::to_address(pi)); + CHECK_EQUAL(plist_item, etl::to_address(itr)); + } }; }