Merge branch 'development' of https://github.com/ETLCPP/etl into development

This commit is contained in:
John Wellbelove 2025-09-10 10:50:09 +01:00
commit 5add8a94a7
4 changed files with 63 additions and 19 deletions

View File

@ -451,8 +451,9 @@ namespace etl
reference create(TArgs&&... args) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
pointer p = ::new (&storage.value) value_type(etl::forward<TArgs>(args)...);
valid = true;
return *::new (&storage.value) value_type(etl::forward<TArgs>(args)...);
return *p;
}
#else
//***************************************************************************
@ -463,8 +464,9 @@ namespace etl
reference create(const T1& t1)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
pointer p = ::new (&storage.value) value_type(t1);
valid = true;
return *::new (&storage.value) value_type(t1);
return *p;
}
//***************************************************************************
@ -475,8 +477,9 @@ namespace etl
reference create(const T1& t1, const T2& t2)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
pointer p = ::new (&storage.value) value_type(t1, t2);
valid = true;
return *::new (&storage.value) value_type(t1, t2);
return *p;
}
//***************************************************************************
@ -487,8 +490,9 @@ namespace etl
reference create(const T1& t1, const T2& t2, const T3& t3)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
pointer p = ::new (&storage.value) value_type(t1, t2, t3);
valid = true;
return *::new (&storage.value) value_type(t1, t2, t3);
return *p;
}
//***************************************************************************
@ -499,8 +503,9 @@ namespace etl
reference create(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
pointer p = ::new (&storage.value) value_type(t1, t2, t3, t4);
valid = true;
return *::new (&storage.value) value_type(t1, t2, t3, t4);
return *p;
}
#endif
@ -559,7 +564,7 @@ namespace etl
struct dummy_t {};
//*******************************
//*******************************
union union_type
{
union_type() ETL_NOEXCEPT
@ -644,6 +649,7 @@ namespace etl
, valid(false)
{
ETL_ASSERT(etl::is_aligned(pbuffer_, etl::alignment_of<T>::value), ETL_ERROR(etl::alignment_error));
create(t1);
}
//***************************************************************************
@ -704,62 +710,67 @@ namespace etl
#if ETL_USING_CPP11
//***************************************************************************
/// Constructs the instance of T forwarding the given \p args to its constructor.
/// \returns the instance of T which has been constructed in the internal byte array.
/// \returns the instance of T which has been constructed in the external buffer.
//***************************************************************************
template <typename... TArgs>
reference create(TArgs&&... args) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
pointer p = ::new (pbuffer) value_type(etl::forward<TArgs>(args)...);
valid = true;
return *::new (pbuffer) value_type(etl::forward<TArgs>(args)...);
return *p;
}
#else
//***************************************************************************
/// Constructs the instance of T with type T1
/// \returns the instance of T which has been constructed in the internal byte array.
/// \returns the instance of T which has been constructed in the external buffer.
//***************************************************************************
template <typename T1>
reference create(const T1& t1)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
pointer p = ::new (pbuffer) value_type(t1);
valid = true;
return *::new (pbuffer) value_type(t1);
return *p;
}
//***************************************************************************
/// Constructs the instance of T with types T1, T2
/// \returns the instance of T which has been constructed in the internal byte array.
/// \returns the instance of T which has been constructed in the external buffer.
//***************************************************************************
template <typename T1, typename T2>
reference create(const T1& t1, const T2& t2)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
pointer p = ::new (pbuffer) value_type(t1, t2);
valid = true;
return *::new (pbuffer) value_type(t1, t2);
return *p;
}
//***************************************************************************
/// Constructs the instance of T with types T1, T2, T3
/// \returns the instance of T which has been constructed in the internal byte array.
/// \returns the instance of T which has been constructed in the external buffer.
//***************************************************************************
template <typename T1, typename T2, typename T3>
reference create(const T1& t1, const T2& t2, const T3& t3)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
pointer p = ::new (pbuffer) value_type(t1, t2, t3);
valid = true;
return *::new (pbuffer) value_type(t1, t2, t3);
return *p;
}
//***************************************************************************
/// Constructs the instance of T with types T1, T2, T3, T4
/// \returns the instance of T which has been constructed in the internal byte array.
/// \returns the instance of T which has been constructed in the external buffer.
//***************************************************************************
template <typename T1, typename T2, typename T3, typename T4>
reference create(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
{
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
pointer p = ::new (pbuffer) value_type(t1, t2, t3, t4);
valid = true;
return *::new (pbuffer) value_type(t1, t2, t3, t4);
return *p;
}
#endif

View File

@ -536,6 +536,17 @@ namespace etl
return storage.u.value;
}
//*************************************************************************
/// Emplaces with zero arguments, i.e. default construct emplace.
//*************************************************************************
ETL_CONSTEXPR20_STL
T& emplace()
{
storage.construct();
return storage.u.value;
}
#else
//*************************************************************************
/// Emplaces a value.

View File

@ -48,6 +48,7 @@ void f(int)
{
}
// Demonstrator class for etl::typed_storage tests
struct A_t
{
A_t(uint32_t v_x, uint8_t v_y)
@ -56,13 +57,22 @@ struct A_t
{
}
// Just for test purpose. In production code, etl::typed_storage
// actually supports the use case of destructors being optimized
// away since they are not necessary for global objects that are
// never destroyed
~A_t()
{
x = 0;
y = 0;
}
bool operator==(A_t& other)
// etl::typed_storage helps implementing the use case of becoming
// independent of the destructor. By deleting the assignment operator,
// we make sure that the destructor is not linked
A_t& operator=(const A_t&) = delete;
bool operator==(const A_t& other) const
{
return other.x == x && other.y == y;
}

View File

@ -218,15 +218,27 @@ namespace
}
//*************************************************************************
TEST(test_emplace_zero_parameters)
TEST(test_emplace_zero_parameters_fundamental)
{
etl::optional<std::uint8_t> result = 1;
result.emplace();
CHECK_EQUAL(0, static_cast<int>(result.emplace()));
CHECK_TRUE(result.has_value());
CHECK_EQUAL(0, int(result.value()));
}
//*************************************************************************
TEST(test_emplace_zero_parameters_non_fundamental)
{
etl::optional<std::string> result = std::string("abc");
std::string& ref = result.emplace();
CHECK_EQUAL(std::string(), ref);
CHECK_EQUAL(&ref, &result.value());
CHECK_TRUE(result.has_value());
CHECK_EQUAL("", std::string(result.value()));
}
//*************************************************************************
TEST(test_emplace_return)
{