diff --git a/library.properties b/library.properties index b2176433..b0890a1f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.16.1 +version=10.17.0 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/variant.h b/src/variant.h index 4bf3d5b9..61d8c892 100644 --- a/src/variant.h +++ b/src/variant.h @@ -112,6 +112,18 @@ namespace etl typename T8 = __private_variant__::no_type<8> > class variant { + public: + + //*************************************************************************** + /// The type used for ids. + //*************************************************************************** + typedef uint_least8_t type_id_t; + + //*************************************************************************** + /// The id a unsupported types. + //*************************************************************************** + static const type_id_t UNSUPPORTED_TYPE_ID = integral_limits::max; + private: // All types of variant are friends. @@ -133,16 +145,6 @@ namespace etl //*************************************************************************** static const size_t ALIGNMENT = etl::largest_alignment::value; - //*************************************************************************** - /// The type used for ids. - //*************************************************************************** - typedef uint_least8_t type_id_t; - - //*************************************************************************** - /// The id a unsupported types. - //*************************************************************************** - static const type_id_t UNSUPPORTED_TYPE_ID = integral_limits::max; - //*************************************************************************** /// Short form of no_type placeholders. //*************************************************************************** @@ -701,6 +703,84 @@ namespace etl type_id = other.type_id; } +#if !ETL_CPP11_SUPPORTED + //*************************************************************************** + /// Emplace with one constructor parameter. + //*************************************************************************** + template + T& emplace(const TP1& value1) + { + STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(value1); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } + + //*************************************************************************** + /// Emplace with two constructor parameters. + //*************************************************************************** + template + T& emplace(const TP1& value1, const TP2& value2) + { + STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(value1, value2); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } + + //*************************************************************************** + /// Emplace with three constructor parameters. + //*************************************************************************** + template + T& emplace(const TP1& value1, const TP2& value2, const TP3& value3) + { + STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(value1, value2, value3); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } + + //*************************************************************************** + /// Emplace with four constructor parameters. + //*************************************************************************** + template + T& emplace(const TP1& value1, const TP2& value2, const TP3& value3, const TP4& value4) + { + STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(value1, value2, value3, value4); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } + +#else + //************************************************************************* + /// Emplace with variadic constructor parameters. + //************************************************************************* + template + T& emplace(Args&&... args) + { + STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(std::forward(args)...); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } +#endif + //*************************************************************************** /// Assignment operator for T1 type. ///\param value The value to assign. @@ -821,6 +901,14 @@ namespace etl return type_id == Type_Id_Lookup::type_id; } + //*************************************************************************** + /// Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID + //*************************************************************************** + ETL_CONSTEXPR size_t index() const + { + return type_id; + } + //*************************************************************************** /// Clears the value to 'no valid stored value'. //*************************************************************************** diff --git a/support/Release notes.txt b/support/Release notes.txt index 5e1cd96c..a02a8180 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +10.17.0 +Added emplace functions to etl::variant. + =============================================================================== 10.16.1 Improved performance of emplace for value_type parameters. diff --git a/test/test_variant.cpp b/test/test_variant.cpp index 5b3324e9..353a3c5b 100644 --- a/test/test_variant.cpp +++ b/test/test_variant.cpp @@ -34,6 +34,7 @@ SOFTWARE. #include #include #include +#include namespace { @@ -99,6 +100,128 @@ namespace // This line should compile with no errors. test_variant_max_types variant_max; + struct D1 + { + D1(const std::string& a_) + : a(a_) + { + } + + std::string a; + }; + + struct D2 + { + D2(const std::string& a_, const std::string& b_) + : a(a_), + b(b_) + { + } + + std::string a; + std::string b; + }; + + struct D3 + { + D3(const std::string& a_, const std::string& b_, const std::string& c_) + : a(a_), + b(b_), + c(c_) + { + } + + std::string a; + std::string b; + std::string c; + }; + + struct D4 + { + D4(const std::string& a_, const std::string& b_, const std::string& c_, const std::string& d_) + : a(a_), + b(b_), + c(c_), + d(d_) + { + } + + std::string a; + std::string b; + std::string c; + std::string d; + }; + + bool operator == (const D1& lhs, const D1& rhs) + { + return (lhs.a == rhs.a); + } + + bool operator == (const D2& lhs, const D2& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b); + } + + bool operator == (const D3& lhs, const D3& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c); + } + + bool operator == (const D4& lhs, const D4& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); + } + + bool operator != (const D1& lhs, const D1& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D2& lhs, const D2& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D3& lhs, const D3& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D4& lhs, const D4& rhs) + { + return !(lhs == rhs); + } + + std::ostream& operator <<(std::ostream& os, const D1& d1) + { + os << d1.a; + + return os; + } + + std::ostream& operator <<(std::ostream& os, const D2& d2) + { + os << d2.a << " " << d2.b; + + return os; + } + + std::ostream& operator <<(std::ostream& os, const D3& d3) + { + os << d3.a << " " << d3.b << " " << d3.c; + + return os; + } + + std::ostream& operator <<(std::ostream& os, const D4& d4) + { + os << d4.a << " " << d4.b << " " << d4.c << " " << d4.d; + + return os; + } + + typedef etl::variant test_variant_emplace; + SUITE(test_variant) { TEST(test_alignment) @@ -666,5 +789,27 @@ namespace variant.upcast().set(); CHECK_EQUAL(2, variant.get().value); } + + //************************************************************************* + TEST(TestEmplace) + { + test_variant_emplace variant; + + variant.emplace("1"); + CHECK(variant.is_type()); + CHECK_EQUAL(D1("1"), variant.get()); + + variant.emplace("1", "2"); + CHECK(variant.is_type()); + CHECK_EQUAL(D2("1", "2"), variant.get()); + + variant.emplace("1", "2", "3"); + CHECK(variant.is_type()); + CHECK_EQUAL(D3("1", "2", "3"), variant.get()); + + variant.emplace("1", "2", "3", "4"); + CHECK(variant.is_type()); + CHECK_EQUAL(D4("1", "2", "3", "4"), variant.get()); + } }; }