Skip to content

Commit 75606fc

Browse files
rolandreichweinbmwJohn Wellbelovedrewr95
authored
Regression fix: Support zero arguments emplace() in etl::optional (#1183)
* Added coderabbitai configuration * Added builtin mem function tests * Modified etl::typed_storage * Modified etl::typed_storage # Conflicts: # include/etl/alignment.h * Added ETL_NOEXCEPT and ETL_NOEXCEPT_IF_NO_THROW * Added etl::typed_storage_ext and swap for same * Added etl::typed_storage_ext and swap for same # Conflicts: # include/etl/alignment.h * Added release notes * Fixes to GCC -O2 errors * Changed char* parameters to value_type* parameters * Fixed compilation issues for const containers unit tests * Added automatic selection of __builtin_memxxx functions for GCC and clang * Added enhanced coderabbit configuration * Updated version and release notes * Disabled constexpr const container tests for C++11 * Attempted fixes for MacOS compilation * Attempted fixes for MacOS compilation * Attempted fixes for MacOS compilation * Attempted fixes for MacOS compilation * Updated version and release notes * feat: removed unreachable break statements (#1169) * Updated version and release notes * Modified etl::typed_storage # Conflicts: # include/etl/alignment.h * Support zero arguments emplace() in etl::optional For non-fundamental types, a recent change in etl::optional was introduced that doesn't support zero arguments emplace() anymore. This change fixes it and adds the respective test. --------- Co-authored-by: John Wellbelove <[email protected]> Co-authored-by: Drew Rife <[email protected]>
1 parent 7301617 commit 75606fc

File tree

3 files changed

+81
-18
lines changed

3 files changed

+81
-18
lines changed

include/etl/alignment.h

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -450,9 +450,17 @@ namespace etl
450450
template <typename... TArgs>
451451
reference create(TArgs&&... args) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
452452
{
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)...);
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;
456464
}
457465
#else
458466
//***************************************************************************
@@ -462,9 +470,17 @@ namespace etl
462470
template <typename T1>
463471
reference create(const T1& t1)
464472
{
465-
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
466-
valid = true;
467-
return *::new (&storage.value) value_type(t1);
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;
468484
}
469485

470486
//***************************************************************************
@@ -474,9 +490,17 @@ namespace etl
474490
template <typename T1, typename T2>
475491
reference create(const T1& t1, const T2& t2)
476492
{
477-
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
478-
valid = true;
479-
return *::new (&storage.value) value_type(t1, t2);
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;
480504
}
481505

482506
//***************************************************************************
@@ -486,9 +510,17 @@ namespace etl
486510
template <typename T1, typename T2, typename T3>
487511
reference create(const T1& t1, const T2& t2, const T3& t3)
488512
{
489-
ETL_ASSERT(!has_value(), ETL_ERROR(etl::typed_storage_error));
490-
valid = true;
491-
return *::new (&storage.value) value_type(t1, t2, t3);
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;
492524
}
493525

494526
//***************************************************************************
@@ -498,9 +530,17 @@ namespace etl
498530
template <typename T1, typename T2, typename T3, typename T4>
499531
reference create(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
500532
{
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);
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;
504544
}
505545
#endif
506546

@@ -559,7 +599,7 @@ namespace etl
559599

560600
struct dummy_t {};
561601

562-
//*******************************
602+
//*******************************
563603
union union_type
564604
{
565605
union_type() ETL_NOEXCEPT

include/etl/optional.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,17 @@ namespace etl
536536

537537
return storage.u.value;
538538
}
539+
540+
//*************************************************************************
541+
/// Emplaces with zero arguments, i.e. default construct emplace.
542+
//*************************************************************************
543+
ETL_CONSTEXPR20_STL
544+
T& emplace()
545+
{
546+
storage.construct();
547+
548+
return storage.u.value;
549+
}
539550
#else
540551
//*************************************************************************
541552
/// Emplaces a value.

test/test_optional.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,15 +218,27 @@ namespace
218218
}
219219

220220
//*************************************************************************
221-
TEST(test_emplace_zero_parameters)
221+
TEST(test_emplace_zero_parameters_fundamental)
222222
{
223223
etl::optional<std::uint8_t> result = 1;
224-
result.emplace();
224+
CHECK_EQUAL(0, static_cast<int>(result.emplace()));
225225

226226
CHECK_TRUE(result.has_value());
227227
CHECK_EQUAL(0, int(result.value()));
228228
}
229229

230+
//*************************************************************************
231+
TEST(test_emplace_zero_parameters_non_fundamental)
232+
{
233+
etl::optional<std::string> result = std::string("abc");
234+
235+
std::string& ref = result.emplace();
236+
CHECK_EQUAL(std::string(), ref);
237+
CHECK_EQUAL(&ref, &result.value());
238+
CHECK_TRUE(result.has_value());
239+
CHECK_EQUAL("", std::string(result.value()));
240+
}
241+
230242
//*************************************************************************
231243
TEST(test_emplace_return)
232244
{

0 commit comments

Comments
 (0)