Add const specialization for etl::get_object_at (#1217)

Signed-off-by: Filipe Cuim <filipemocuim@gmail.com>
This commit is contained in:
Filipe Cuim 2025-11-11 19:12:39 +00:00 committed by GitHub
parent b6e78b7c9c
commit 43d3f0e89c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 76 additions and 38 deletions

View File

@ -60,8 +60,8 @@ namespace etl
//*****************************************************************************
template <typename T>
ETL_CONSTEXPR T* to_address(T* p) ETL_NOEXCEPT
{
return p;
{
return p;
}
//*****************************************************************************
@ -837,7 +837,7 @@ namespace etl
std::uninitialized_value_construct(o_begin, o_end);
}
#else
#else
//*****************************************************************************
/// Default initialises a range of objects to uninitialised memory.
/// https://en.cppreference.com/w/cpp/memory/uninitialized_value_construct
@ -1264,7 +1264,7 @@ namespace etl
//*********************************
template <typename U>
default_delete(const default_delete<U>&) ETL_NOEXCEPT
default_delete(const default_delete<U>&) ETL_NOEXCEPT
{
}
@ -1353,8 +1353,8 @@ namespace etl
#endif
//*********************************
unique_ptr(pointer p_, typename etl::conditional<etl::is_reference<TDeleter>::value,
TDeleter,
unique_ptr(pointer p_, typename etl::conditional<etl::is_reference<TDeleter>::value,
TDeleter,
typename etl::add_lvalue_reference<const TDeleter>::type>::type deleter_) ETL_NOEXCEPT
: p(p_)
, deleter(deleter_)
@ -1557,7 +1557,7 @@ namespace etl
#endif
//*********************************
unique_ptr(pointer p_,
unique_ptr(pointer p_,
typename etl::conditional<etl::is_reference<TDeleter>::value,
TDeleter,
typename etl::add_lvalue_reference<const TDeleter>::type>::type deleter_) ETL_NOEXCEPT
@ -1614,7 +1614,7 @@ namespace etl
{
pointer value = p;
p = ETL_NULLPTR;
return value;
return value;
}
//*********************************
@ -1709,7 +1709,7 @@ namespace etl
unique_ptr(const unique_ptr&) ETL_DELETE;
unique_ptr& operator =(const unique_ptr&) ETL_DELETE;
pointer p;
pointer p;
TDeleter deleter;
};
}
@ -2324,7 +2324,7 @@ namespace etl
reinterpret_cast<const void*>(sb),
sizeof(T) * n);
#endif
return db;
}
@ -2374,7 +2374,7 @@ namespace etl
reinterpret_cast<const void*>(sb),
sizeof(T) * n);
#endif
return db;
}
@ -2438,7 +2438,7 @@ namespace etl
/// \return The destination
//***************************************************************************
template <typename TPointer, typename T>
typename etl::enable_if<etl::is_pointer<TPointer>::value &&
typename etl::enable_if<etl::is_pointer<TPointer>::value &&
!etl::is_const<TPointer>::value &&
etl::is_integral<T>::value &&
sizeof(T) == 1, TPointer>::type
@ -2447,11 +2447,11 @@ namespace etl
ETL_STATIC_ASSERT(etl::is_trivially_copyable<typename etl::iterator_traits<TPointer>::value_type>::value, "Cannot mem_set a non trivially copyable type");
#if ETL_USING_BUILTIN_MEMSET
__builtin_memset(reinterpret_cast<void*>(db),
__builtin_memset(reinterpret_cast<void*>(db),
static_cast<char>(value),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * static_cast<size_t>(de - db));
#else
::memset(reinterpret_cast<void*>(db),
::memset(reinterpret_cast<void*>(db),
static_cast<char>(value),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * static_cast<size_t>(de - db));
#endif
@ -2504,13 +2504,13 @@ namespace etl
mem_char(TPointer sb, TPointer se, T value) ETL_NOEXCEPT
{
#if ETL_USING_BUILTIN_MEMCHR
void* result = __builtin_memchr(reinterpret_cast<void*>(sb),
void* result = __builtin_memchr(reinterpret_cast<void*>(sb),
static_cast<char>(value),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * static_cast<size_t>(se - sb));
return (result == 0U) ? reinterpret_cast<char*>(se) : reinterpret_cast<char*>(result);
#else
void* result = ::memchr(reinterpret_cast<void*>(sb),
void* result = ::memchr(reinterpret_cast<void*>(sb),
static_cast<char>(value),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * static_cast<size_t>(se - sb));
@ -2527,7 +2527,7 @@ namespace etl
//***************************************************************************
template <typename TPointer, typename T>
ETL_NODISCARD
typename etl::enable_if<etl::is_pointer<TPointer>::value &&
typename etl::enable_if<etl::is_pointer<TPointer>::value &&
etl::is_const<typename etl::remove_pointer<TPointer>::type>::value &&
etl::is_integral<T>::value &&
sizeof(T) == 1, const char*>::type
@ -2545,7 +2545,7 @@ namespace etl
sizeof(typename etl::iterator_traits<TPointer>::value_type) * static_cast<size_t>(se - sb));
return (result == 0U) ? reinterpret_cast<const char*>(se) : reinterpret_cast<const char*>(result);
#endif
#endif
}
//***************************************************************************
@ -2557,25 +2557,25 @@ namespace etl
//***************************************************************************
template <typename TPointer, typename T>
ETL_NODISCARD
typename etl::enable_if<etl::is_pointer<TPointer>::value &&
typename etl::enable_if<etl::is_pointer<TPointer>::value &&
!etl::is_const<typename etl::remove_pointer<TPointer>::type>::value &&
etl::is_integral<T>::value &&
sizeof(T) == 1, char*>::type
mem_char(TPointer sb, size_t n, T value) ETL_NOEXCEPT
{
#if ETL_USING_BUILTIN_MEMCHR
void* result = __builtin_memchr(reinterpret_cast<void*>(sb),
void* result = __builtin_memchr(reinterpret_cast<void*>(sb),
static_cast<char>(value),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * n);
return (result == 0U) ? reinterpret_cast<char*>(sb + n) : reinterpret_cast<char*>(result);
#else
void* result = ::memchr(reinterpret_cast<void*>(sb),
void* result = ::memchr(reinterpret_cast<void*>(sb),
static_cast<char>(value),
sizeof(typename etl::iterator_traits<TPointer>::value_type) * n);
return (result == 0U) ? reinterpret_cast<char*>(sb + n) : reinterpret_cast<char*>(result);
#endif
#endif
}
//***************************************************************************
@ -2587,7 +2587,7 @@ namespace etl
//***************************************************************************
template <typename TPointer, typename T>
ETL_NODISCARD
typename etl::enable_if<etl::is_pointer<TPointer>::value &&
typename etl::enable_if<etl::is_pointer<TPointer>::value &&
etl::is_const<typename etl::remove_pointer<TPointer>::type>::value &&
etl::is_integral<T>::value &&
sizeof(T) == 1, const char*>::type
@ -2607,7 +2607,7 @@ namespace etl
return (result == 0U) ? reinterpret_cast<const char*>(sb + n) : reinterpret_cast<const char*>(result);
#endif
}
#if ETL_USING_CPP11
@ -2687,9 +2687,20 @@ namespace etl
ETL_ASSERT(is_aligned<TObject>(p), ETL_ERROR(alignment_error));
#endif
TObject& v = *reinterpret_cast<TObject*>(p);
return *reinterpret_cast<TObject*>(p);
}
return v;
//*****************************************************************************
/// Get the container at const 'p'.
//*****************************************************************************
template <typename TObject>
const TObject& get_object_at(const void* p)
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(is_aligned<TObject>(p), ETL_ERROR(alignment_error));
#endif
return *reinterpret_cast<const TObject*>(p);
}
//*****************************************************************************

View File

@ -1256,7 +1256,7 @@ namespace
uint32_t expected[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 };
uint32_t data[12] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201, 0, 0, 0, 0 };
const uint32_t* data_begin = &data[0];
uint32_t* result = etl::mem_move(data_begin, 8, data + 4);
CHECK(std::equal(expected, expected + 8, data + 4));
CHECK(result == data + 4);
@ -1269,7 +1269,7 @@ namespace
uint32_t same[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 };
uint32_t grtr[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67235501, 0x45016723, 0x01324576, 0x76453201 };
uint32_t less[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67134501, 0x45016723, 0x01324576, 0x76453201 };
CHECK(etl::mem_compare(data, data + 8, same) == 0);
CHECK(etl::mem_compare(data, data + 8, grtr) > 0);
CHECK(etl::mem_compare(data, data + 8, less) < 0);
@ -1443,7 +1443,7 @@ namespace
}
//*************************************************************************
class Base
class Base
{
public:
virtual ~Base() {};
@ -1452,21 +1452,21 @@ namespace
static bool function_was_called = false;
class Derived : public Base
class Derived : public Base
{
public:
Derived()
Derived()
{
function_was_called = false;
}
void function()
void function()
{
function_was_called = true;
}
};
void call(etl::unique_ptr<Base> ptr)
void call(etl::unique_ptr<Base> ptr)
{
ptr->function();
}
@ -1477,13 +1477,13 @@ namespace
etl::unique_ptr<Derived> ptr(new Derived());
CHECK(ptr.get() != ETL_NULLPTR);
call(etl::move(ptr));
CHECK(function_was_called);
CHECK(ptr.get() == ETL_NULLPTR);
}
struct Flags
{
Flags()
@ -1530,7 +1530,7 @@ namespace
int a;
int b;
};
alignas(Data) char buffer1[sizeof(Data)];
char* pbuffer1 = buffer1;
@ -1581,14 +1581,14 @@ namespace
CHECK_FALSE(flags.destructed);
CHECK_EQUAL(1, rdata1b.a);
CHECK_EQUAL(2, rdata1b.b);
flags.Clear();
Data& rdata2b = etl::get_object_at<Data>(pbuffer2b);
CHECK_FALSE(flags.constructed);
CHECK_FALSE(flags.destructed);
CHECK_EQUAL(data2.a, rdata2b.a);
CHECK_EQUAL(data2.b, rdata2b.b);
flags.Clear();
Data& rdata3b = etl::get_object_at<Data>(pbuffer3b);
CHECK_FALSE(flags.constructed);
@ -1612,6 +1612,33 @@ namespace
CHECK_TRUE(flags.destructed);
}
TEST(test_get_object_at_const_specialization)
{
struct Data
{
Data()
: a(1)
, b(2)
{
flags.constructed = true;
}
~Data() = default;
int a;
int b;
};
std::array<uint8_t, 32U> buffer{};
etl::construct_object_at(buffer.data(), Data());
const void* bufferPointer = buffer.data();
const Data& rdata = etl::get_object_at<Data>(bufferPointer);
CHECK_TRUE(flags.constructed);
CHECK_TRUE(rdata.a == 1);
CHECK_TRUE(rdata.b == 2);
}
TEST(test_construct_get_destroy_object_misaligned)
{
struct Data