From a0af0f94152201eb9777b4bf9222110de5448153 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 14 Jun 2023 09:14:44 +0100 Subject: [PATCH] Modified the POD specialisation to accept objects that have deleted default constructors --- include/etl/optional.h | 53 +++++++++++++++++++++++++++++------------- test/test_optional.cpp | 14 +++++++---- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/include/etl/optional.h b/include/etl/optional.h index 47517b6c..2e28ff75 100644 --- a/include/etl/optional.h +++ b/include/etl/optional.h @@ -700,8 +700,8 @@ namespace etl //*************************************************************************** ETL_CONSTEXPR14 optional(const T& value_) : valid(true) - , storage(value_) { + storage.u.value = value_; } #if ETL_USING_CPP11 @@ -710,8 +710,8 @@ namespace etl //*************************************************************************** ETL_CONSTEXPR14 optional(T&& value_) : valid(true) - , storage(etl::move(value_)) { + storage.u.value = etl::move(value_); } #endif @@ -731,7 +731,7 @@ namespace etl { if (this != &other) { - storage = other.storage; + storage.u = other.storage.u; valid = other.valid; } @@ -746,7 +746,7 @@ namespace etl { if (this != &other) { - storage = etl::move(other.storage); + storage.u = etl::move(other.storage.u); valid = other.valid; } @@ -759,7 +759,7 @@ namespace etl //*************************************************************************** ETL_CONSTEXPR14 optional& operator =(const T& value_) { - storage = value_; + storage.u.value = value_; valid = true; return *this; @@ -771,7 +771,7 @@ namespace etl //*************************************************************************** ETL_CONSTEXPR14 optional& operator =(T&& value_) { - storage = etl::move(value_); + storage.u.value = etl::move(value_); valid = true; return *this; @@ -878,7 +878,7 @@ namespace etl ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); #endif - return storage; + return storage.u.value; } //*************************************************************************** @@ -890,7 +890,7 @@ namespace etl ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); #endif - return storage; + return storage.u.value; } //*************************************************************************** @@ -911,7 +911,7 @@ namespace etl ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); #endif - return etl::move(storage); + return etl::move(storage.u.value); } //*************************************************************************** @@ -923,7 +923,7 @@ namespace etl ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); #endif - return etl::move(storage); + return etl::move(storage.u.value); } //*************************************************************************** @@ -961,7 +961,7 @@ namespace etl template ETL_CONSTEXPR14 void emplace(Args && ... args) { - storage = T(ETL_OR_STD::forward(args)...); + storage.u.value = T(ETL_OR_STD::forward(args)...); valid = true; } #else @@ -972,7 +972,7 @@ namespace etl template void emplace(const T1& value1) { - storage = value1; + storage.u.value = value1; valid = true; } @@ -983,7 +983,7 @@ namespace etl template void emplace(const T1& value1, const T2& value2) { - storage = T(value1, value2); + storage.u.value = T(value1, value2); valid = true; } @@ -994,7 +994,7 @@ namespace etl template void emplace(const T1& value1, const T2& value2, const T3& value3) { - storage = T(value1, value2, value3); + storage.u.value = T(value1, value2, value3); valid = true; } @@ -1005,7 +1005,7 @@ namespace etl template void emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4) { - storage = T(value1, value2, value3, value4); + storage.u.value = T(value1, value2, value3, value4); valid = true; } #endif @@ -1013,7 +1013,28 @@ namespace etl private: bool valid; - T storage; + + struct storage_type + { + storage_type() + { + } + + union union_type + { + union_type() + : dummy(0) + { + } + + char dummy; + T value; + }; + + union_type u; + }; + + storage_type storage; }; #include "etl/private/diagnostic_uninitialized_push.h" diff --git a/test/test_optional.cpp b/test/test_optional.cpp index 8ca78f6b..e6a9a832 100644 --- a/test/test_optional.cpp +++ b/test/test_optional.cpp @@ -495,12 +495,18 @@ namespace } //************************************************************************* - TEST(test_optional_pod_assign_bug_714) + struct MyPODObject { - etl::optional o = 42; - o = etl::nullopt; + MyPODObject() = delete; + int value; + }; - CHECK_EQUAL(false, o.has_value()); + TEST(test_optional_pod_emplace_bug_712) + { + etl::optional optionalObject; // The Test: Does this compile for an object with a deleted default constructor? + + // Make sure it isn't optimised away. + CHECK_FALSE(optionalObject.has_value()); } }; }