Skip to content

Commit f3c8151

Browse files
Fix etl::typed_storage by supporting omitted destructors
In a recent change to alignment.h, the etl::typed_storage was changed in a way that in case of an already constructed object, the object is created via assignment. However, this contradicts the original use case that led to etl::typed_storage in the first place: ETLCPP#1023 The goal is to omit destructors (and at the same time support classes with deleted assignment operators), so they can be optimized out at link time. This change reverts commit ac7b268 to restore the original functionality and changes the test to reflect the original use case.
1 parent 7324388 commit f3c8151

File tree

2 files changed

+25
-55
lines changed

2 files changed

+25
-55
lines changed

include/etl/alignment.h

Lines changed: 15 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -450,17 +450,9 @@ namespace etl
450450
template <typename... TArgs>
451451
reference create(TArgs&&... args) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
452452
{
453-
if (has_value())
454-
{
455-
storage.value = T(args...);
456-
}
457-
else
458-
{
459-
valid = true;
460-
::new (&storage.value) value_type(etl::forward<TArgs>(args)...);
461-
}
462-
463-
return storage.value;
453+
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
454+
valid = true;
455+
return *::new (&storage.value) value_type(etl::forward<TArgs>(args)...);
464456
}
465457
#else
466458
//***************************************************************************
@@ -470,17 +462,9 @@ namespace etl
470462
template <typename T1>
471463
reference create(const T1& t1)
472464
{
473-
if (has_value())
474-
{
475-
storage.value = T(t1);
476-
}
477-
else
478-
{
479-
valid = true;
480-
::new (&storage.value) value_type(t1);
481-
}
482-
483-
return storage.value;
465+
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
466+
valid = true;
467+
return *::new (&storage.value) value_type(t1);
484468
}
485469

486470
//***************************************************************************
@@ -490,17 +474,9 @@ namespace etl
490474
template <typename T1, typename T2>
491475
reference create(const T1& t1, const T2& t2)
492476
{
493-
if (has_value())
494-
{
495-
storage.value = T(t1, t2);
496-
}
497-
else
498-
{
499-
valid = true;
500-
::new (&storage.value) value_type(t1, t2);
501-
}
502-
503-
return storage.value;
477+
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
478+
valid = true;
479+
return *::new (&storage.value) value_type(t1, t2);
504480
}
505481

506482
//***************************************************************************
@@ -510,17 +486,9 @@ namespace etl
510486
template <typename T1, typename T2, typename T3>
511487
reference create(const T1& t1, const T2& t2, const T3& t3)
512488
{
513-
if (has_value())
514-
{
515-
storage.value = T(t1, t2, t3);
516-
}
517-
else
518-
{
519-
valid = true;
520-
::new (&storage.value) value_type(t1, t2, t3);
521-
}
522-
523-
return storage.value;
489+
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
490+
valid = true;
491+
return *::new (&storage.value) value_type(t1, t2, t3);
524492
}
525493

526494
//***************************************************************************
@@ -530,17 +498,9 @@ namespace etl
530498
template <typename T1, typename T2, typename T3, typename T4>
531499
reference create(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
532500
{
533-
if (has_value())
534-
{
535-
storage.value = T(t1, t2, t3, t4);
536-
}
537-
else
538-
{
539-
valid = true;
540-
::new (&storage.value) value_type(t1, t2, t3, t4);
541-
}
542-
543-
return storage.value;
501+
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
502+
valid = true;
503+
return *::new (&storage.value) value_type(t1, t2, t3, t4);
544504
}
545505
#endif
546506

test/test_alignment.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ void f(int)
4848
{
4949
}
5050

51+
// Demonstrator class for etl::typed_storage tests
5152
struct A_t
5253
{
5354
A_t(uint32_t v_x, uint8_t v_y)
@@ -56,12 +57,21 @@ struct A_t
5657
{
5758
}
5859

60+
// Just for test purpose. In production code, etl::typed_storage
61+
// actually supports the use case of destructors being optimized
62+
// away since they are not necessary for global objects that are
63+
// never destroyed
5964
~A_t()
6065
{
6166
x = 0;
6267
y = 0;
6368
}
6469

70+
// etl::typed_storage helps implementing the use case of becoming
71+
// independent of the destructor. By deleting the assignment operator,
72+
// we make sure that the destructor is not linked
73+
A_t& operator=(A_t& other) = delete;
74+
6575
bool operator==(A_t& other)
6676
{
6777
return other.x == x && other.y == y;

0 commit comments

Comments
 (0)