mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Added etl::contruct_object_at, etl::get_object_at and etl::destroy_object_at
This commit is contained in:
parent
2c15062c1b
commit
7316c07045
@ -100,5 +100,6 @@ SOFTWARE.
|
||||
#define ETL_BIP_BUFFER_SPSC_ATOMIC_FILE_ID "67"
|
||||
#define ETL_REFERENCE_COUNTED_OBJECT_FILE_ID "68"
|
||||
#define ETL_TO_ARITHMETIC_FILE_ID "69"
|
||||
#define ETL_ALIGNMENT_FILE_ID "70"
|
||||
|
||||
#endif
|
||||
|
||||
@ -2446,6 +2446,103 @@ namespace etl
|
||||
|
||||
return (result == 0U) ? reinterpret_cast<const char*>(sb + n) : reinterpret_cast<const char*>(result);
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*****************************************************************************
|
||||
/// Move construct the container at 'p'.
|
||||
//*****************************************************************************
|
||||
template <typename TObject>
|
||||
TObject& construct_object_at(void* p, TObject&& other)
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(is_aligned<TObject>(p), ETL_ERROR(alignment_error));
|
||||
#endif
|
||||
|
||||
return *etl::construct_at(reinterpret_cast<typename etl::remove_reference<TObject>::type*>(p), etl::forward<TObject>(other));
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Construct the container at 'p' from arguments.
|
||||
//*****************************************************************************
|
||||
template <typename TObject, typename... TArgs>
|
||||
TObject& construct_object_at(void* p, TArgs&&... args)
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(is_aligned<TObject>(p), ETL_ERROR(alignment_error));
|
||||
#endif
|
||||
|
||||
return *etl::construct_at(reinterpret_cast<TObject*>(p), etl::forward<TArgs>(args)...);
|
||||
}
|
||||
#else
|
||||
//*****************************************************************************
|
||||
/// Default construct the container at 'p'.
|
||||
//*****************************************************************************
|
||||
template <typename TObject>
|
||||
TObject& construct_object_at(void* p)
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(is_aligned<TObject>(p), ETL_ERROR(alignment_error));
|
||||
#endif
|
||||
|
||||
return *etl::construct_at(reinterpret_cast<TObject*>(p));
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Copy construct the container at 'p'.
|
||||
//*****************************************************************************
|
||||
template <typename TObject>
|
||||
TObject& construct_object_at(void* p, const TObject& other)
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(is_aligned<TObject>(p), ETL_ERROR(alignment_error));
|
||||
#endif
|
||||
|
||||
return *etl::construct_at(reinterpret_cast<TObject*>(p), other);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Construct the container at 'p' from argument.
|
||||
//*****************************************************************************
|
||||
template <typename TObject, typename TArg>
|
||||
TObject& construct_object_at(void* p, const TArg& arg)
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(is_aligned<TObject>(p), ETL_ERROR(alignment_error));
|
||||
#endif
|
||||
|
||||
return *etl::construct_at(reinterpret_cast<TObject*>(p), arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
/// Get the container at 'p'.
|
||||
//*****************************************************************************
|
||||
template <typename TObject>
|
||||
TObject& get_object_at(void* p)
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(is_aligned<TObject>(p), ETL_ERROR(alignment_error));
|
||||
#endif
|
||||
|
||||
TObject& v = *reinterpret_cast<TObject*>(p);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Destroy the container at 'p'.
|
||||
/// For a container that contains a type that is not trivially destructible.
|
||||
//*****************************************************************************
|
||||
template <typename TObject>
|
||||
void destroy_object_at(void* p)
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(is_aligned<TObject>(p), ETL_ERROR(alignment_error));
|
||||
#endif
|
||||
|
||||
TObject& v = get_object_at<TObject>(p);
|
||||
v.~TObject();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -1344,5 +1344,179 @@ namespace
|
||||
CHECK(function_was_called);
|
||||
CHECK(ptr.get() == ETL_NULLPTR);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
struct Flags
|
||||
{
|
||||
Flags()
|
||||
: constructed(false)
|
||||
, destructed(false)
|
||||
{
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
constructed = false;
|
||||
destructed = false;
|
||||
}
|
||||
|
||||
bool constructed;
|
||||
bool destructed;
|
||||
};
|
||||
|
||||
static Flags flags;
|
||||
|
||||
TEST(test_construct_get_destroy_object_aligned)
|
||||
{
|
||||
struct Data
|
||||
{
|
||||
Data()
|
||||
: a(1)
|
||||
, b(2)
|
||||
{
|
||||
flags.constructed = true;
|
||||
}
|
||||
|
||||
Data(int a_, int b_)
|
||||
: a(a_)
|
||||
, b(b_)
|
||||
{
|
||||
flags.constructed = true;
|
||||
}
|
||||
|
||||
~Data()
|
||||
{
|
||||
flags.destructed = true;
|
||||
}
|
||||
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
alignas(Data) char buffer1[sizeof(Data)];
|
||||
char* pbuffer1 = buffer1;
|
||||
|
||||
alignas(Data) char buffer1b[sizeof(Data)];
|
||||
char* pbuffer1b = buffer1b;
|
||||
|
||||
alignas(Data) char buffer2[sizeof(Data)];
|
||||
char* pbuffer2 = buffer2;
|
||||
|
||||
alignas(Data) char buffer2b[sizeof(Data)];
|
||||
char* pbuffer2b = buffer2b;
|
||||
|
||||
alignas(Data) char buffer3[sizeof(Data)];
|
||||
char* pbuffer3 = buffer3;
|
||||
|
||||
alignas(Data) char buffer3b[sizeof(Data)];
|
||||
char* pbuffer3b = buffer3b;
|
||||
|
||||
flags.Clear();
|
||||
Data& rdata1 = etl::construct_object_at<Data>(pbuffer1);
|
||||
CHECK_TRUE(flags.constructed);
|
||||
CHECK_FALSE(flags.destructed);
|
||||
CHECK_EQUAL(1, rdata1.a);
|
||||
CHECK_EQUAL(2, rdata1.b);
|
||||
|
||||
flags.Clear();
|
||||
Data data2(3, 4);
|
||||
Data& rdata2 = etl::construct_object_at(pbuffer2, data2);
|
||||
CHECK_TRUE(flags.constructed);
|
||||
CHECK_FALSE(flags.destructed);
|
||||
CHECK_EQUAL(data2.a, rdata2.a);
|
||||
CHECK_EQUAL(data2.b, rdata2.b);
|
||||
|
||||
flags.Clear();
|
||||
Data& rdata3 = etl::construct_object_at<Data>(pbuffer3, 5, 6);
|
||||
CHECK_TRUE(flags.constructed);
|
||||
CHECK_FALSE(flags.destructed);
|
||||
CHECK_EQUAL(5, rdata3.a);
|
||||
CHECK_EQUAL(6, rdata3.b);
|
||||
|
||||
memcpy(buffer1b, buffer1, sizeof(Data));
|
||||
memcpy(buffer2b, buffer2, sizeof(Data));
|
||||
memcpy(buffer3b, buffer3, sizeof(Data));
|
||||
|
||||
flags.Clear();
|
||||
Data& rdata1b = etl::get_object_at<Data>(pbuffer1b);
|
||||
CHECK_FALSE(flags.constructed);
|
||||
CHECK_FALSE(flags.destructed);
|
||||
CHECK_EQUAL(1, rdata1.a);
|
||||
CHECK_EQUAL(2, rdata1.b);
|
||||
|
||||
flags.Clear();
|
||||
Data& rdata2b = etl::get_object_at<Data>(pbuffer2b);
|
||||
CHECK_FALSE(flags.constructed);
|
||||
CHECK_FALSE(flags.destructed);
|
||||
CHECK_EQUAL(data2.a, rdata2.a);
|
||||
CHECK_EQUAL(data2.b, rdata2.b);
|
||||
|
||||
flags.Clear();
|
||||
Data& rdata3b = etl::get_object_at<Data>(pbuffer3b);
|
||||
CHECK_FALSE(flags.constructed);
|
||||
CHECK_FALSE(flags.destructed);
|
||||
CHECK_EQUAL(5, rdata3.a);
|
||||
CHECK_EQUAL(6, rdata3.b);
|
||||
|
||||
flags.Clear();
|
||||
etl::destroy_object_at<Data>(pbuffer1b);
|
||||
CHECK_FALSE(flags.constructed);
|
||||
CHECK_TRUE(flags.destructed);
|
||||
|
||||
flags.Clear();
|
||||
etl::destroy_object_at<Data>(pbuffer2b);
|
||||
CHECK_FALSE(flags.constructed);
|
||||
CHECK_TRUE(flags.destructed);
|
||||
|
||||
flags.Clear();
|
||||
etl::destroy_object_at<Data>(pbuffer3b);
|
||||
CHECK_FALSE(flags.constructed);
|
||||
CHECK_TRUE(flags.destructed);
|
||||
}
|
||||
|
||||
TEST(test_construct_get_destroy_object_misaligned)
|
||||
{
|
||||
struct Data
|
||||
{
|
||||
Data()
|
||||
: a(1)
|
||||
, b(2)
|
||||
{
|
||||
}
|
||||
|
||||
Data(int a_, int b_)
|
||||
: a(a_)
|
||||
, b(b_)
|
||||
{
|
||||
}
|
||||
|
||||
~Data()
|
||||
{
|
||||
}
|
||||
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
alignas(Data) char buffer1[sizeof(Data)];
|
||||
char* pbuffer1 = buffer1 + 1;
|
||||
|
||||
alignas(Data) char buffer2[sizeof(Data)];
|
||||
char* pbuffer2 = buffer2 + 1;
|
||||
|
||||
alignas(Data) char buffer3[sizeof(Data)];
|
||||
char* pbuffer3 = buffer3 + 1;
|
||||
|
||||
CHECK_THROW(etl::construct_object_at<Data>(pbuffer1), etl::alignment_error);
|
||||
|
||||
Data data2(3, 4);
|
||||
CHECK_THROW(etl::construct_object_at(pbuffer2, data2), etl::alignment_error);
|
||||
|
||||
CHECK_THROW(etl::construct_object_at<Data>(pbuffer3, 5, 6), etl::alignment_error);
|
||||
|
||||
CHECK_THROW(etl::get_object_at<Data>(pbuffer1), etl::alignment_error);
|
||||
|
||||
CHECK_THROW(etl::destroy_object_at<Data>(pbuffer1), etl::alignment_error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user