diff --git a/include/etl/private/variant_variadic.h b/include/etl/private/variant_variadic.h index b76ba7a6..b2b8771e 100644 --- a/include/etl/private/variant_variadic.h +++ b/include/etl/private/variant_variadic.h @@ -1400,6 +1400,8 @@ namespace etl void do_destroy() { do_destroy_impl(etl::integral_constant{}); + + type_id = variant_npos; } void do_destroy_impl(etl::integral_constant) diff --git a/test/test_variant_variadic.cpp b/test/test_variant_variadic.cpp index 11cef693..0680f79a 100644 --- a/test/test_variant_variadic.cpp +++ b/test/test_variant_variadic.cpp @@ -1097,6 +1097,71 @@ namespace } #endif + #if ETL_USING_EXCEPTIONS + //************************************************************************* + // A throwing emplace() must leave the variant valueless-after-exception + // (index() == variant_npos) rather than reporting the stale old index. + struct ThrowOnConstruct + { + struct exception + { + }; + + ThrowOnConstruct() = default; + explicit ThrowOnConstruct(int) + { + throw exception(); + } + }; + + TEST(test_emplace_throwing_is_valueless_by_exception) + { + // Trivially destructible suite (variadic_union storage). + { + etl::variant v; + v.emplace(42); + CHECK(!v.valueless_by_exception()); + CHECK_EQUAL(0U, v.index()); + + bool threw = false; + try + { + v.emplace(1); + } + catch (const ThrowOnConstruct::exception&) + { + threw = true; + } + + CHECK(threw); + CHECK(v.valueless_by_exception()); + CHECK_EQUAL(etl::variant_npos, v.index()); + } + + // Non-trivially destructible suite (uninitialized_buffer storage). + { + etl::variant v; + v.emplace("Some Text"); + CHECK(!v.valueless_by_exception()); + CHECK_EQUAL(0U, v.index()); + + bool threw = false; + try + { + v.emplace<1>(1); + } + catch (const ThrowOnConstruct::exception&) + { + threw = true; + } + + CHECK(threw); + CHECK(v.valueless_by_exception()); + CHECK_EQUAL(etl::variant_npos, v.index()); + } + } + #endif + //************************************************************************* TEST(test_copy_constructor) {