mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Modified etl::typed_storage
This commit is contained in:
parent
5f8b7f7120
commit
0081cfa794
@ -368,109 +368,147 @@ namespace etl
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
// Constructor
|
||||
//***************************************************************************
|
||||
// Default constructor
|
||||
//***************************************************************************
|
||||
typed_storage()
|
||||
: valid(false)
|
||||
{
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Constructs the instance of T forwarding the given \p args to its constructor.
|
||||
//***************************************************************************
|
||||
template <typename... TArgs>
|
||||
typed_storage(TArgs&&... args)
|
||||
{
|
||||
create(etl::forward<TArgs>(args)...);
|
||||
}
|
||||
#else
|
||||
//***************************************************************************
|
||||
/// Constructs the instance of T with type T1
|
||||
//***************************************************************************
|
||||
typed_storage(const T1& t1)
|
||||
{
|
||||
create(t1);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructs the instance of T with types T1, T2
|
||||
//***************************************************************************
|
||||
typed_storage(const T1& t1, const T2& t2)
|
||||
{
|
||||
create(t1, t2);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructs the instance of T with types T1, T2, T3
|
||||
//***************************************************************************
|
||||
typed_storage(const T1& t1, const T2& t2, const T3& t3)
|
||||
{
|
||||
create(t1, t2, t3);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructs the instance of T with types T1, T2, T3, T4
|
||||
//***************************************************************************
|
||||
typed_storage(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
{
|
||||
create(t1, t2, t3, t4);
|
||||
}
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Default destructor which will NOT call the destructor of the object which
|
||||
/// was created by calling create().
|
||||
//***************************************************************************
|
||||
~typed_storage()
|
||||
{
|
||||
// Intentionally empty.
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// \returns <b>true</b> if object has been constructed using create().
|
||||
/// \returns <b>false</b> otherwise.
|
||||
//***************************************************************************
|
||||
bool has_value() const
|
||||
bool has_value() const ETL_NOEXCEPT
|
||||
{
|
||||
return valid;
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Constructs the instance of T forwarding the given \p args to its constructor and
|
||||
/// asserts if has_value() is false.
|
||||
///
|
||||
/// 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.
|
||||
//***************************************************************************
|
||||
template<typename... Args>
|
||||
reference create(Args&&... args)
|
||||
template <typename... TArgs>
|
||||
reference create(TArgs&&... args)
|
||||
{
|
||||
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
|
||||
valid = true;
|
||||
return *::new (data.template get_address<char>()) value_type(etl::forward<Args>(args)...);
|
||||
return *::new (&storage.value) value_type(etl::forward<TArgs>(args)...);
|
||||
}
|
||||
#else
|
||||
//***************************************************************************
|
||||
/// Constructs the instance of T with type T1
|
||||
/// asserts if has_value() is false.
|
||||
///
|
||||
/// \returns the instance of T which has been constructed in the internal byte array.
|
||||
//***************************************************************************
|
||||
template<typename T1>
|
||||
template <typename T1>
|
||||
reference create(const T1& t1)
|
||||
{
|
||||
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
|
||||
valid = true;
|
||||
return *::new (data.template get_address<char>()) value_type(t1);
|
||||
return *::new (&storage.value) value_type(t1);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructs the instance of T with types T1, T2
|
||||
/// asserts if has_value() is false.
|
||||
///
|
||||
/// \returns the instance of T which has been constructed in the internal byte array.
|
||||
//***************************************************************************
|
||||
template<typename T1, typename T2>
|
||||
template <typename T1, typename T2>
|
||||
reference create(const T1& t1, const T2& t2)
|
||||
{
|
||||
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
|
||||
valid = true;
|
||||
return *::new (data.template get_address<char>()) value_type(t1, t2);
|
||||
return *::new (&storage.value) value_type(t1, t2);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructs the instance of T with types T1, T2, T3
|
||||
/// asserts if has_value() is false.
|
||||
///
|
||||
/// \returns the instance of T which has been constructed in the internal byte array.
|
||||
//***************************************************************************
|
||||
template<typename T1, typename T2, typename T3>
|
||||
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));
|
||||
valid = true;
|
||||
return *::new (data.template get_address<char>()) value_type(t1, t2, t3);
|
||||
return *::new (&storage.value) value_type(t1, t2, t3);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Constructs the instance of T with types T1, T2, T3, T4
|
||||
/// asserts if has_value() is false.
|
||||
///
|
||||
/// \returns the instance of T which has been constructed in the internal byte array.
|
||||
//***************************************************************************
|
||||
template<typename T1, typename T2, typename T3, typename T4>
|
||||
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));
|
||||
valid = true;
|
||||
return *::new (data.template get_address<char>()) value_type(t1, t2, t3, t4);
|
||||
return *::new (&storage.value) value_type(t1, t2, t3, t4);
|
||||
}
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Calls the destructor of the wrapped object and asserts if has_value() is false.
|
||||
/// Calls the destructor of the stored object, if created.
|
||||
//***************************************************************************
|
||||
void destroy()
|
||||
{
|
||||
ETL_ASSERT(has_value(), ETL_ERROR(etl::typed_storage_error));
|
||||
data.template get_reference<T>().~T();
|
||||
valid = false;
|
||||
if (has_value())
|
||||
{
|
||||
storage.value.~T();
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
@ -479,7 +517,8 @@ namespace etl
|
||||
pointer operator->()
|
||||
{
|
||||
ETL_ASSERT(has_value(), ETL_ERROR(etl::typed_storage_error));
|
||||
return data.template get_address<value_type>();
|
||||
|
||||
return &storage.value;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
@ -487,7 +526,9 @@ namespace etl
|
||||
//***************************************************************************
|
||||
const_pointer operator->() const
|
||||
{
|
||||
return operator->();
|
||||
ETL_ASSERT(has_value(), ETL_ERROR(etl::typed_storage_error));
|
||||
|
||||
return &storage.value;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
@ -499,7 +540,7 @@ namespace etl
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// \returns const reference of type T and asserts if has_value() is false.
|
||||
/// \returns const_reference of type T and asserts if has_value() is false.
|
||||
//***************************************************************************
|
||||
const_reference operator*() const
|
||||
{
|
||||
@ -508,7 +549,27 @@ namespace etl
|
||||
|
||||
private:
|
||||
|
||||
typename aligned_storage_as<sizeof(value_type), value_type>::type data;
|
||||
typed_storage(etl::typed_storage<T>&) ETL_DELETE;
|
||||
typed_storage& operator =(etl::typed_storage<T>&) ETL_DELETE;
|
||||
|
||||
struct dummy_t {};
|
||||
|
||||
//*******************************
|
||||
union union_type
|
||||
{
|
||||
union_type()
|
||||
: dummy()
|
||||
{
|
||||
}
|
||||
|
||||
~union_type()
|
||||
{
|
||||
}
|
||||
|
||||
dummy_t dummy;
|
||||
T value;
|
||||
} storage;
|
||||
|
||||
bool valid;
|
||||
};
|
||||
}
|
||||
|
||||
@ -194,24 +194,31 @@ namespace
|
||||
TEST(test_typed_storage)
|
||||
{
|
||||
etl::typed_storage<A_t> a;
|
||||
CHECK_FALSE(a.has_value());
|
||||
|
||||
CHECK_EQUAL(false, a.has_value());
|
||||
|
||||
auto& b = a.create(123, 4);
|
||||
|
||||
CHECK_EQUAL(true, a.has_value());
|
||||
etl::typed_storage<A_t> b(789, 10); // Construct in place.
|
||||
CHECK_TRUE(b.has_value());
|
||||
CHECK_EQUAL(b->x, 789);
|
||||
CHECK_EQUAL(b->y, 10);
|
||||
|
||||
auto& ref = a.create(123, 4); // Create in place.
|
||||
CHECK_TRUE(a.has_value());
|
||||
|
||||
CHECK_EQUAL(a->x, 123);
|
||||
CHECK_EQUAL(a->y, 4);
|
||||
|
||||
CHECK_EQUAL(b.x, 123);
|
||||
CHECK_EQUAL(b.y, 4);
|
||||
CHECK_EQUAL(ref.x, 123);
|
||||
CHECK_EQUAL(ref.y, 4);
|
||||
|
||||
CHECK_TRUE(*a == b);
|
||||
CHECK_TRUE(*a == ref);
|
||||
|
||||
CHECK_EQUAL(true, a.has_value());
|
||||
a.create(456, 7); // Calling create again is not an error.
|
||||
CHECK_EQUAL(a->x, 456);
|
||||
CHECK_EQUAL(a->y, 7);
|
||||
|
||||
CHECK_TRUE(a.has_value());
|
||||
a.destroy();
|
||||
CHECK_EQUAL(false, a.has_value());
|
||||
CHECK_FALSE(a.has_value());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user