From 820bc36aa621c33e644b24eba23fca07479eb9ce Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 21 May 2021 18:05:02 +0100 Subject: [PATCH] Initial commit --- include/etl/private/variant_legacy.h | 1028 +++++++++++++++++++++++++ include/etl/private/variant_new.h | 1037 ++++++++++++++++++++++++++ include/etl/variant.h | 999 +------------------------ test/vs2019/etl.vcxproj | 2 + test/vs2019/etl.vcxproj.filters | 6 + 5 files changed, 2076 insertions(+), 996 deletions(-) create mode 100644 include/etl/private/variant_legacy.h create mode 100644 include/etl/private/variant_new.h diff --git a/include/etl/private/variant_legacy.h b/include/etl/private/variant_legacy.h new file mode 100644 index 00000000..cd85638e --- /dev/null +++ b/include/etl/private/variant_legacy.h @@ -0,0 +1,1028 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include + +#include "../platform.h" +#include "../utility.h" +#include "../array.h" +#include "../largest.h" +#include "../exception.h" +#include "../type_traits.h" +#include "../integral_limits.h" +#include "../static_assert.h" +#include "../alignment.h" +#include "../error_handler.h" +#include "../null_type.h" +#include "../placement_new.h" + +#if defined(ETL_COMPILER_KEIL) + #pragma diag_suppress 940 + #pragma diag_suppress 111 +#endif + +//***************************************************************************** +///\defgroup variant variant +/// A class that can contain one a several specified types in a type safe manner. +///\ingroup containers +//***************************************************************************** + +namespace etl +{ + namespace private_variant + { + //************************************************************************* + /// Placeholder for unused template parameters. + /// This class is never instantiated. + //************************************************************************* + template + struct no_type + { + }; + } + + //*************************************************************************** + /// Base exception for the variant class. + ///\ingroup variant + //*************************************************************************** + class variant_exception : public exception + { + public: + variant_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// 'Unsupported type' exception for the variant class. + ///\ingroup variant + //*************************************************************************** + class variant_incorrect_type_exception : public variant_exception + { + public: + variant_incorrect_type_exception(string_type file_name_, numeric_type line_number_) + : variant_exception(ETL_ERROR_TEXT("variant: unsupported type", ETL_VARIANT_FILE_ID"A"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// A template class that can store any of the types defined in the template parameter list. + /// Supports up to 8 types. + ///\ingroup variant + //*************************************************************************** + template , + typename T3 = etl::null_type<3>, + typename T4 = etl::null_type<4>, + typename T5 = etl::null_type<5>, + typename T6 = etl::null_type<6>, + typename T7 = etl::null_type<7>, + typename T8 = etl::null_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. + template + friend class variant; + + //*************************************************************************** + /// The largest type. + //*************************************************************************** + typedef typename largest_type::type largest_t; + + //*************************************************************************** + /// The largest size. + //*************************************************************************** + static const size_t SIZE = sizeof(largest_t); + + //*************************************************************************** + /// The largest alignment. + //*************************************************************************** + static const size_t ALIGNMENT = etl::largest_alignment::value; + + //*************************************************************************** + /// Short form of no_type placeholders. + //*************************************************************************** + typedef etl::null_type<2> no_type2; + typedef etl::null_type<3> no_type3; + typedef etl::null_type<4> no_type4; + typedef etl::null_type<5> no_type5; + typedef etl::null_type<6> no_type6; + typedef etl::null_type<7> no_type7; + typedef etl::null_type<8> no_type8; + + //*************************************************************************** + /// Lookup the id of type. + //*************************************************************************** + template + struct Type_Id_Lookup + { + static const uint_least8_t type_id = etl::is_same::value ? 0 : + etl::is_same::value ? 1 : + etl::is_same::value ? 2 : + etl::is_same::value ? 3 : + etl::is_same::value ? 4 : + etl::is_same::value ? 5 : + etl::is_same::value ? 6 : + etl::is_same::value ? 7 : + UNSUPPORTED_TYPE_ID; + }; + + //*************************************************************************** + /// Lookup for the id of type. + //*************************************************************************** + template + struct Type_Is_Supported : public integral_constant::value || + is_same::value || + is_same::value || + is_same::value || + is_same::value || + is_same::value || + is_same::value || + is_same::value> + { + }; + + public: + + //*************************************************************************** + /// Destructor. + //*************************************************************************** + ~variant() + { + destruct_current(); + } + + //************************************************************************* + //**** Reader types ******************************************************* + //************************************************************************* + + //************************************************************************* + /// Base reader type functor class. + /// Allows for typesafe access to the stored value types. + /// Define the reader type for 8 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + }; + + //************************************************************************* + /// Define the reader type for 7 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 6 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 5 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type6&) {}; + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 4 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type5&) {}; + void read(no_type6&) {}; + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 3 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type4&) {}; + void read(no_type5&) {}; + void read(no_type6&) {}; + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 2 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type3&) {}; + void read(no_type4&) {}; + void read(no_type5&) {}; + void read(no_type6&) {}; + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 1 type. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type2&) {}; + void read(no_type3&) {}; + void read(no_type4&) {}; + void read(no_type5&) {}; + void read(no_type6&) {}; + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //*************************************************************************** + /// The base type for derived readers. + //*************************************************************************** + typedef reader_type reader; + + //*************************************************************************** + /// Default constructor. + /// Sets the state of the instance to containing no valid data. + //*************************************************************************** + variant() + : type_id(UNSUPPORTED_TYPE_ID) + { + } + + //*************************************************************************** + /// Constructor that catches any types that are not supported. + /// Forces a ETL_STATIC_ASSERT. + //*************************************************************************** + template + variant(const T& value) + { + ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + ::new (static_cast(data)) T(value); + type_id = Type_Id_Lookup::type_id; + } + + //*************************************************************************** + /// Copy constructor. + ///\param other The other variant object to copy. + //*************************************************************************** + variant(const variant& other) + { + switch (other.type_id) + { + case 0: ::new (static_cast(data)) T1(other.get()); break; + case 1: ::new (static_cast(data)) T2(other.get()); break; + case 2: ::new (static_cast(data)) T3(other.get()); break; + case 3: ::new (static_cast(data)) T4(other.get()); break; + case 4: ::new (static_cast(data)) T5(other.get()); break; + case 5: ::new (static_cast(data)) T6(other.get()); break; + case 6: ::new (static_cast(data)) T7(other.get()); break; + case 7: ::new (static_cast(data)) T8(other.get()); break; + default: break; + } + + type_id = other.type_id; + } + +#if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && !defined(ETL_VARIANT_FORCE_CPP03) + //************************************************************************* + /// Emplace with variadic constructor parameters. + //************************************************************************* + template + T& emplace(Args&&... args) + { + ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(etl::forward(args)...); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } +#else + //*************************************************************************** + /// Emplace with one constructor parameter. + //*************************************************************************** + template + T& emplace(const TP1& value1) + { + ETL_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) + { + ETL_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) + { + ETL_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) + { + ETL_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); + } +#endif + + //*************************************************************************** + /// Assignment operator for T1 type. + ///\param value The value to assign. + //*************************************************************************** + template + variant& operator =(const T& value) + { + ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(value); + type_id = Type_Id_Lookup::type_id; + + return *this; + } + + //*************************************************************************** + /// Assignment operator for variant type. + ///\param other The variant to assign. + //*************************************************************************** + variant& operator =(const variant& other) + { + if (this != &other) + { + destruct_current(); + + switch (other.type_id) + { + case 0: ::new (static_cast(data)) T1(other.get()); break; + case 1: ::new (static_cast(data)) T2(other.get()); break; + case 2: ::new (static_cast(data)) T3(other.get()); break; + case 3: ::new (static_cast(data)) T4(other.get()); break; + case 4: ::new (static_cast(data)) T5(other.get()); break; + case 5: ::new (static_cast(data)) T6(other.get()); break; + case 6: ::new (static_cast(data)) T7(other.get()); break; + case 7: ::new (static_cast(data)) T8(other.get()); break; + default: break; + } + + type_id = other.type_id; + } + + return *this; + } + + //*************************************************************************** + /// Checks if the type is the same as the current stored type. + /// For variants with the same type declarations. + ///\return true if the types are the same, otherwise false. + //*************************************************************************** + bool is_same_type(const variant& other) const + { + return type_id == other.type_id; + } + + //*************************************************************************** + /// Checks if the type is the same as the current stored type. + /// For variants with differing declarations. + ///\return true if the types are the same, otherwise false. + //*************************************************************************** + template + bool is_same_type(const variant& other) const + { + bool is_same = false; + + switch (other.type_id) + { + case 0: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 1: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 2: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 3: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 4: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 5: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 6: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 7: is_same = (type_id == Type_Id_Lookup::type_id); break; + default: break; + } + + return is_same; + } + + //*************************************************************************** + /// Calls the supplied reader instance. + /// The 'read' function appropriate to the current type is called with the stored value. + //*************************************************************************** + void call(reader& r) + { + switch (type_id) + { + case 0: r.read(static_cast(data)); break; + case 1: r.read(static_cast(data)); break; + case 2: r.read(static_cast(data)); break; + case 3: r.read(static_cast(data)); break; + case 4: r.read(static_cast(data)); break; + case 5: r.read(static_cast(data)); break; + case 6: r.read(static_cast(data)); break; + case 7: r.read(static_cast(data)); break; + default: break; + } + } + + //*************************************************************************** + /// Checks whether a valid value is currently stored. + ///\return true if the value is valid, otherwise false. + //*************************************************************************** + bool is_valid() const + { + return type_id != UNSUPPORTED_TYPE_ID; + } + + //*************************************************************************** + /// Checks to see if the type currently stored is the same as that specified in the template parameter. + ///\return true if it is the specified type, otherwise false. + //*************************************************************************** + template + bool is_type() const + { + return type_id == Type_Id_Lookup::type_id; + } + + //*************************************************************************** + /// Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID + //*************************************************************************** + size_t index() const + { + return type_id; + } + + //*************************************************************************** + /// Clears the value to 'no valid stored value'. + //*************************************************************************** + void clear() + { + destruct_current(); + } + + //*************************************************************************** + /// Gets the value stored as the specified template type. + /// Throws a variant_incorrect_type_exception if the actual type is not that specified. + ///\return A reference to the value. + //*************************************************************************** + template + T& get() + { + ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + ETL_ASSERT(is_type(), ETL_ERROR(variant_incorrect_type_exception)); + + return static_cast(data); + } + + //*************************************************************************** + /// Gets the value stored as the specified template type. + /// Throws a variant_incorrect_type_exception if the actual type is not that specified. + ///\return A const reference to the value. + //*************************************************************************** + template + const T& get() const + { + ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + ETL_ASSERT(is_type(), ETL_ERROR(variant_incorrect_type_exception)); + + return static_cast(data); + } + + //*************************************************************************** + /// Gets the value stored as the specified template type. + ///\return A reference to the value. + //*************************************************************************** + template + TBase& upcast() + { + return *upcast_functor()(data, type_id); + } + + //*************************************************************************** + /// Gets the value stored as the specified template type. + ///\return A const reference to the value. + //*************************************************************************** + template + const TBase& upcast() const + { + return *upcast_functor()(data, type_id); + } + + //*************************************************************************** + /// Conversion operators for each type. + //*************************************************************************** + operator T1&() { return get(); } + operator T2&() { return get(); } + operator T3&() { return get(); } + operator T4&() { return get(); } + operator T5&() { return get(); } + operator T6&() { return get(); } + operator T7&() { return get(); } + operator T8&() { return get(); } + + //*************************************************************************** + /// Checks if the template type is supported by the implementation of variant.. + ///\return true if the type is supported, otherwise false. + //*************************************************************************** + template + static bool is_supported_type() + { + return Type_Is_Supported::value; + } + + private: + + //*************************************************************************** + /// Destruct the current occupant of the variant. + //*************************************************************************** + void destruct_current() + { + switch (type_id) + { + case 0: { static_cast(data)->~T1(); break; } + case 1: { static_cast(data)->~T2(); break; } + case 2: { static_cast(data)->~T3(); break; } + case 3: { static_cast(data)->~T4(); break; } + case 4: { static_cast(data)->~T5(); break; } + case 5: { static_cast(data)->~T6(); break; } + case 6: { static_cast(data)->~T7(); break; } + case 7: { static_cast(data)->~T8(); break; } + default: { break; } + } + + type_id = UNSUPPORTED_TYPE_ID; + } + + //************************************************************************* + //**** Up-cast functors *************************************************** + //************************************************************************* + + //************************************************************************* + /// Base upcast_functor for eight types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + case 6: return reinterpret_cast(p_data); + case 7: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + case 6: return reinterpret_cast(p_data); + case 7: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for seven types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + case 6: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + case 6: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for six types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for five types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for four types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for three types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for two types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for one type. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //*************************************************************************** + /// The internal storage. + /// Aligned on a suitable boundary, which should be good for all types. + //*************************************************************************** + typename etl::aligned_storage::type data; + + //*************************************************************************** + /// The id of the current stored type. + //*************************************************************************** + type_id_t type_id; + }; +} diff --git a/include/etl/private/variant_new.h b/include/etl/private/variant_new.h new file mode 100644 index 00000000..c40985e1 --- /dev/null +++ b/include/etl/private/variant_new.h @@ -0,0 +1,1037 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include + +#include "../platform.h" +#include "../utility.h" +#include "../array.h" +#include "../largest.h" +#include "../exception.h" +#include "../type_traits.h" +#include "../integral_limits.h" +#include "../static_assert.h" +#include "../alignment.h" +#include "../error_handler.h" +#include "../null_type.h" +#include "../placement_new.h" + +#if defined(ETL_COMPILER_KEIL) + #pragma diag_suppress 940 + #pragma diag_suppress 111 +#endif + +//***************************************************************************** +///\defgroup variant variant +/// A class that can contain one a several specified types in a type safe manner. +///\ingroup containers +//***************************************************************************** + +namespace etl +{ + namespace private_variant + { + //************************************************************************* + /// Placeholder for unused template parameters. + /// This class is never instantiated. + //************************************************************************* + template + struct no_type + { + }; + + template + struct index_of_type; + + template + struct index_of_type : etl::integral_constant {}; + + template + struct index_of_type : etl::integral_constant::value> {}; + } + + //*************************************************************************** + /// Base exception for the variant class. + ///\ingroup variant + //*************************************************************************** + class variant_exception : public exception + { + public: + variant_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// 'Unsupported type' exception for the variant class. + ///\ingroup variant + //*************************************************************************** + class variant_incorrect_type_exception : public variant_exception + { + public: + variant_incorrect_type_exception(string_type file_name_, numeric_type line_number_) + : variant_exception(ETL_ERROR_TEXT("variant: unsupported type", ETL_VARIANT_FILE_ID"A"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// A template class that can store any of the types defined in the template parameter list. + /// Supports up to 8 types. + ///\ingroup variant + //*************************************************************************** + template , + typename T3 = etl::null_type<3>, + typename T4 = etl::null_type<4>, + typename T5 = etl::null_type<5>, + typename T6 = etl::null_type<6>, + typename T7 = etl::null_type<7>, + typename T8 = etl::null_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. + template + friend class variant; + + //*************************************************************************** + /// The largest type. + //*************************************************************************** + typedef typename largest_type::type largest_t; + + //*************************************************************************** + /// The largest size. + //*************************************************************************** + static const size_t SIZE = sizeof(largest_t); + + //*************************************************************************** + /// The largest alignment. + //*************************************************************************** + static const size_t ALIGNMENT = etl::largest_alignment::value; + + //*************************************************************************** + /// Short form of no_type placeholders. + //*************************************************************************** + typedef etl::null_type<2> no_type2; + typedef etl::null_type<3> no_type3; + typedef etl::null_type<4> no_type4; + typedef etl::null_type<5> no_type5; + typedef etl::null_type<6> no_type6; + typedef etl::null_type<7> no_type7; + typedef etl::null_type<8> no_type8; + + //*************************************************************************** + /// Lookup the id of type. + //*************************************************************************** + template + struct Type_Id_Lookup + { + static const uint_least8_t type_id = etl::is_same::value ? 0 : + etl::is_same::value ? 1 : + etl::is_same::value ? 2 : + etl::is_same::value ? 3 : + etl::is_same::value ? 4 : + etl::is_same::value ? 5 : + etl::is_same::value ? 6 : + etl::is_same::value ? 7 : + UNSUPPORTED_TYPE_ID; + }; + + //*************************************************************************** + /// Lookup for the id of type. + //*************************************************************************** + template + struct Type_Is_Supported : public integral_constant::value || + is_same::value || + is_same::value || + is_same::value || + is_same::value || + is_same::value || + is_same::value || + is_same::value> + { + }; + + public: + + //*************************************************************************** + /// Destructor. + //*************************************************************************** + ~variant() + { + destruct_current(); + } + + //************************************************************************* + //**** Reader types ******************************************************* + //************************************************************************* + + //************************************************************************* + /// Base reader type functor class. + /// Allows for typesafe access to the stored value types. + /// Define the reader type for 8 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + }; + + //************************************************************************* + /// Define the reader type for 7 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 6 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 5 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type6&) {}; + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 4 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type5&) {}; + void read(no_type6&) {}; + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 3 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type4&) {}; + void read(no_type5&) {}; + void read(no_type6&) {}; + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 2 types. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type3&) {}; + void read(no_type4&) {}; + void read(no_type5&) {}; + void read(no_type6&) {}; + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //************************************************************************* + /// Define the reader type for 1 type. + //************************************************************************* + template + class reader_type + { + public: + + friend class variant; + + virtual void read(typename etl::parameter_type::type value) = 0; + + private: + + void read(no_type2&) {}; + void read(no_type3&) {}; + void read(no_type4&) {}; + void read(no_type5&) {}; + void read(no_type6&) {}; + void read(no_type7&) {}; + void read(no_type8&) {}; + }; + + //*************************************************************************** + /// The base type for derived readers. + //*************************************************************************** + typedef reader_type reader; + + //*************************************************************************** + /// Default constructor. + /// Sets the state of the instance to containing no valid data. + //*************************************************************************** + variant() + : type_id(UNSUPPORTED_TYPE_ID) + { + } + + //*************************************************************************** + /// Constructor that catches any types that are not supported. + /// Forces a ETL_STATIC_ASSERT. + //*************************************************************************** + template + variant(const T& value) + { + ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + ::new (static_cast(data)) T(value); + type_id = Type_Id_Lookup::type_id; + } + + //*************************************************************************** + /// Copy constructor. + ///\param other The other variant object to copy. + //*************************************************************************** + variant(const variant& other) + { + switch (other.type_id) + { + case 0: ::new (static_cast(data)) T1(other.get()); break; + case 1: ::new (static_cast(data)) T2(other.get()); break; + case 2: ::new (static_cast(data)) T3(other.get()); break; + case 3: ::new (static_cast(data)) T4(other.get()); break; + case 4: ::new (static_cast(data)) T5(other.get()); break; + case 5: ::new (static_cast(data)) T6(other.get()); break; + case 6: ::new (static_cast(data)) T7(other.get()); break; + case 7: ::new (static_cast(data)) T8(other.get()); break; + default: break; + } + + type_id = other.type_id; + } + +#if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && !defined(ETL_VARIANT_FORCE_CPP03) + //************************************************************************* + /// Emplace with variadic constructor parameters. + //************************************************************************* + template + T& emplace(Args&&... args) + { + ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(etl::forward(args)...); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } +#else + //*************************************************************************** + /// Emplace with one constructor parameter. + //*************************************************************************** + template + T& emplace(const TP1& value1) + { + ETL_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) + { + ETL_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) + { + ETL_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) + { + ETL_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); + } +#endif + + //*************************************************************************** + /// Assignment operator for T1 type. + ///\param value The value to assign. + //*************************************************************************** + template + variant& operator =(const T& value) + { + ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(value); + type_id = Type_Id_Lookup::type_id; + + return *this; + } + + //*************************************************************************** + /// Assignment operator for variant type. + ///\param other The variant to assign. + //*************************************************************************** + variant& operator =(const variant& other) + { + if (this != &other) + { + destruct_current(); + + switch (other.type_id) + { + case 0: ::new (static_cast(data)) T1(other.get()); break; + case 1: ::new (static_cast(data)) T2(other.get()); break; + case 2: ::new (static_cast(data)) T3(other.get()); break; + case 3: ::new (static_cast(data)) T4(other.get()); break; + case 4: ::new (static_cast(data)) T5(other.get()); break; + case 5: ::new (static_cast(data)) T6(other.get()); break; + case 6: ::new (static_cast(data)) T7(other.get()); break; + case 7: ::new (static_cast(data)) T8(other.get()); break; + default: break; + } + + type_id = other.type_id; + } + + return *this; + } + + //*************************************************************************** + /// Checks if the type is the same as the current stored type. + /// For variants with the same type declarations. + ///\return true if the types are the same, otherwise false. + //*************************************************************************** + bool is_same_type(const variant& other) const + { + return type_id == other.type_id; + } + + //*************************************************************************** + /// Checks if the type is the same as the current stored type. + /// For variants with differing declarations. + ///\return true if the types are the same, otherwise false. + //*************************************************************************** + template + bool is_same_type(const variant& other) const + { + bool is_same = false; + + switch (other.type_id) + { + case 0: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 1: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 2: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 3: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 4: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 5: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 6: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 7: is_same = (type_id == Type_Id_Lookup::type_id); break; + default: break; + } + + return is_same; + } + + //*************************************************************************** + /// Calls the supplied reader instance. + /// The 'read' function appropriate to the current type is called with the stored value. + //*************************************************************************** + void call(reader& r) + { + switch (type_id) + { + case 0: r.read(static_cast(data)); break; + case 1: r.read(static_cast(data)); break; + case 2: r.read(static_cast(data)); break; + case 3: r.read(static_cast(data)); break; + case 4: r.read(static_cast(data)); break; + case 5: r.read(static_cast(data)); break; + case 6: r.read(static_cast(data)); break; + case 7: r.read(static_cast(data)); break; + default: break; + } + } + + //*************************************************************************** + /// Checks whether a valid value is currently stored. + ///\return true if the value is valid, otherwise false. + //*************************************************************************** + bool is_valid() const + { + return type_id != UNSUPPORTED_TYPE_ID; + } + + //*************************************************************************** + /// Checks to see if the type currently stored is the same as that specified in the template parameter. + ///\return true if it is the specified type, otherwise false. + //*************************************************************************** + template + bool is_type() const + { + return type_id == Type_Id_Lookup::type_id; + } + + //*************************************************************************** + /// Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID + //*************************************************************************** + size_t index() const + { + return type_id; + } + + //*************************************************************************** + /// Clears the value to 'no valid stored value'. + //*************************************************************************** + void clear() + { + destruct_current(); + } + + //*************************************************************************** + /// Gets the value stored as the specified template type. + /// Throws a variant_incorrect_type_exception if the actual type is not that specified. + ///\return A reference to the value. + //*************************************************************************** + template + T& get() + { + ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + ETL_ASSERT(is_type(), ETL_ERROR(variant_incorrect_type_exception)); + + return static_cast(data); + } + + //*************************************************************************** + /// Gets the value stored as the specified template type. + /// Throws a variant_incorrect_type_exception if the actual type is not that specified. + ///\return A const reference to the value. + //*************************************************************************** + template + const T& get() const + { + ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + ETL_ASSERT(is_type(), ETL_ERROR(variant_incorrect_type_exception)); + + return static_cast(data); + } + + //*************************************************************************** + /// Gets the value stored as the specified template type. + ///\return A reference to the value. + //*************************************************************************** + template + TBase& upcast() + { + return *upcast_functor()(data, type_id); + } + + //*************************************************************************** + /// Gets the value stored as the specified template type. + ///\return A const reference to the value. + //*************************************************************************** + template + const TBase& upcast() const + { + return *upcast_functor()(data, type_id); + } + + //*************************************************************************** + /// Conversion operators for each type. + //*************************************************************************** + operator T1&() { return get(); } + operator T2&() { return get(); } + operator T3&() { return get(); } + operator T4&() { return get(); } + operator T5&() { return get(); } + operator T6&() { return get(); } + operator T7&() { return get(); } + operator T8&() { return get(); } + + //*************************************************************************** + /// Checks if the template type is supported by the implementation of variant.. + ///\return true if the type is supported, otherwise false. + //*************************************************************************** + template + static bool is_supported_type() + { + return Type_Is_Supported::value; + } + + private: + + //*************************************************************************** + /// Destruct the current occupant of the variant. + //*************************************************************************** + void destruct_current() + { + switch (type_id) + { + case 0: { static_cast(data)->~T1(); break; } + case 1: { static_cast(data)->~T2(); break; } + case 2: { static_cast(data)->~T3(); break; } + case 3: { static_cast(data)->~T4(); break; } + case 4: { static_cast(data)->~T5(); break; } + case 5: { static_cast(data)->~T6(); break; } + case 6: { static_cast(data)->~T7(); break; } + case 7: { static_cast(data)->~T8(); break; } + default: { break; } + } + + type_id = UNSUPPORTED_TYPE_ID; + } + + //************************************************************************* + //**** Up-cast functors *************************************************** + //************************************************************************* + + //************************************************************************* + /// Base upcast_functor for eight types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + case 6: return reinterpret_cast(p_data); + case 7: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + case 6: return reinterpret_cast(p_data); + case 7: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for seven types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + case 6: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + case 6: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for six types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + case 5: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for five types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + case 4: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for four types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + case 3: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for three types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + case 2: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for two types. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + case 1: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //************************************************************************* + /// Upcast_functor for one type. + //************************************************************************* + template + class upcast_functor + { + public: + + TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + + const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const + { + switch (typeId) + { + case 0: return reinterpret_cast(p_data); + default: return reinterpret_cast(0); + } + } + }; + + //*************************************************************************** + /// The internal storage. + /// Aligned on a suitable boundary, which should be good for all types. + //*************************************************************************** + typename etl::aligned_storage::type data; + + //*************************************************************************** + /// The id of the current stored type. + //*************************************************************************** + type_id_t type_id; + }; +} diff --git a/include/etl/variant.h b/include/etl/variant.h index c466cf07..8702eeed 100644 --- a/include/etl/variant.h +++ b/include/etl/variant.h @@ -31,1003 +31,10 @@ SOFTWARE. #ifndef ETL_VARIANT_INCLUDED #define ETL_VARIANT_INCLUDED -#include - -#include "platform.h" -#include "utility.h" -#include "array.h" -#include "largest.h" -#include "exception.h" -#include "type_traits.h" -#include "integral_limits.h" -#include "static_assert.h" -#include "alignment.h" -#include "error_handler.h" -#include "null_type.h" -#include "placement_new.h" - -#if defined(ETL_COMPILER_KEIL) - #pragma diag_suppress 940 - #pragma diag_suppress 111 -#endif - -//***************************************************************************** -///\defgroup variant variant -/// A class that can contain one a several specified types in a type safe manner. -///\ingroup containers -//***************************************************************************** - -namespace etl -{ - namespace private_variant - { - //************************************************************************* - /// Placeholder for unused template parameters. - /// This class is never instantiated. - //************************************************************************* - template - struct no_type - { - }; - } - - //*************************************************************************** - /// Base exception for the variant class. - ///\ingroup variant - //*************************************************************************** - class variant_exception : public exception - { - public: - variant_exception(string_type reason_, string_type file_name_, numeric_type line_number_) - : exception(reason_, file_name_, line_number_) - { - } - }; - - //*************************************************************************** - /// 'Unsupported type' exception for the variant class. - ///\ingroup variant - //*************************************************************************** - class variant_incorrect_type_exception : public variant_exception - { - public: - variant_incorrect_type_exception(string_type file_name_, numeric_type line_number_) - : variant_exception(ETL_ERROR_TEXT("variant: unsupported type", ETL_VARIANT_FILE_ID"A"), file_name_, line_number_) - { - } - }; - - //*************************************************************************** - /// A template class that can store any of the types defined in the template parameter list. - /// Supports up to 8 types. - ///\ingroup variant - //*************************************************************************** - template , - typename T3 = etl::null_type<3>, - typename T4 = etl::null_type<4>, - typename T5 = etl::null_type<5>, - typename T6 = etl::null_type<6>, - typename T7 = etl::null_type<7>, - typename T8 = etl::null_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. - template - friend class variant; - - //*************************************************************************** - /// The largest type. - //*************************************************************************** - typedef typename largest_type::type largest_t; - - //*************************************************************************** - /// The largest size. - //*************************************************************************** - static const size_t SIZE = sizeof(largest_t); - - //*************************************************************************** - /// The largest alignment. - //*************************************************************************** - static const size_t ALIGNMENT = etl::largest_alignment::value; - - //*************************************************************************** - /// Short form of no_type placeholders. - //*************************************************************************** - typedef etl::null_type<2> no_type2; - typedef etl::null_type<3> no_type3; - typedef etl::null_type<4> no_type4; - typedef etl::null_type<5> no_type5; - typedef etl::null_type<6> no_type6; - typedef etl::null_type<7> no_type7; - typedef etl::null_type<8> no_type8; - - //*************************************************************************** - /// Lookup the id of type. - //*************************************************************************** - template - struct Type_Id_Lookup - { - static const uint_least8_t type_id = etl::is_same::value ? 0 : - etl::is_same::value ? 1 : - etl::is_same::value ? 2 : - etl::is_same::value ? 3 : - etl::is_same::value ? 4 : - etl::is_same::value ? 5 : - etl::is_same::value ? 6 : - etl::is_same::value ? 7 : - UNSUPPORTED_TYPE_ID; - }; - - //*************************************************************************** - /// Lookup for the id of type. - //*************************************************************************** - template - struct Type_Is_Supported : public integral_constant::value || - is_same::value || - is_same::value || - is_same::value || - is_same::value || - is_same::value || - is_same::value || - is_same::value> - { - }; - - public: - - //*************************************************************************** - /// Destructor. - //*************************************************************************** - ~variant() - { - destruct_current(); - } - - //************************************************************************* - //**** Reader types ******************************************************* - //************************************************************************* - - //************************************************************************* - /// Base reader type functor class. - /// Allows for typesafe access to the stored value types. - /// Define the reader type for 8 types. - //************************************************************************* - template - class reader_type - { - public: - - friend class variant; - - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - }; - - //************************************************************************* - /// Define the reader type for 7 types. - //************************************************************************* - template - class reader_type - { - public: - - friend class variant; - - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - - private: - - void read(no_type8&) {}; - }; - - //************************************************************************* - /// Define the reader type for 6 types. - //************************************************************************* - template - class reader_type - { - public: - - friend class variant; - - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - - private: - - void read(no_type7&) {}; - void read(no_type8&) {}; - }; - - //************************************************************************* - /// Define the reader type for 5 types. - //************************************************************************* - template - class reader_type - { - public: - - friend class variant; - - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - - private: - - void read(no_type6&) {}; - void read(no_type7&) {}; - void read(no_type8&) {}; - }; - - //************************************************************************* - /// Define the reader type for 4 types. - //************************************************************************* - template - class reader_type - { - public: - - friend class variant; - - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - - private: - - void read(no_type5&) {}; - void read(no_type6&) {}; - void read(no_type7&) {}; - void read(no_type8&) {}; - }; - - //************************************************************************* - /// Define the reader type for 3 types. - //************************************************************************* - template - class reader_type - { - public: - - friend class variant; - - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - - private: - - void read(no_type4&) {}; - void read(no_type5&) {}; - void read(no_type6&) {}; - void read(no_type7&) {}; - void read(no_type8&) {}; - }; - - //************************************************************************* - /// Define the reader type for 2 types. - //************************************************************************* - template - class reader_type - { - public: - - friend class variant; - - virtual void read(typename etl::parameter_type::type value) = 0; - virtual void read(typename etl::parameter_type::type value) = 0; - - private: - - void read(no_type3&) {}; - void read(no_type4&) {}; - void read(no_type5&) {}; - void read(no_type6&) {}; - void read(no_type7&) {}; - void read(no_type8&) {}; - }; - - //************************************************************************* - /// Define the reader type for 1 type. - //************************************************************************* - template - class reader_type - { - public: - - friend class variant; - - virtual void read(typename etl::parameter_type::type value) = 0; - - private: - - void read(no_type2&) {}; - void read(no_type3&) {}; - void read(no_type4&) {}; - void read(no_type5&) {}; - void read(no_type6&) {}; - void read(no_type7&) {}; - void read(no_type8&) {}; - }; - - //*************************************************************************** - /// The base type for derived readers. - //*************************************************************************** - typedef reader_type reader; - - //*************************************************************************** - /// Default constructor. - /// Sets the state of the instance to containing no valid data. - //*************************************************************************** - variant() - : type_id(UNSUPPORTED_TYPE_ID) - { - } - - //*************************************************************************** - /// Constructor that catches any types that are not supported. - /// Forces a ETL_STATIC_ASSERT. - //*************************************************************************** - template - variant(const T& value) - { - ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); - - ::new (static_cast(data)) T(value); - type_id = Type_Id_Lookup::type_id; - } - - //*************************************************************************** - /// Copy constructor. - ///\param other The other variant object to copy. - //*************************************************************************** - variant(const variant& other) - { - switch (other.type_id) - { - case 0: ::new (static_cast(data)) T1(other.get()); break; - case 1: ::new (static_cast(data)) T2(other.get()); break; - case 2: ::new (static_cast(data)) T3(other.get()); break; - case 3: ::new (static_cast(data)) T4(other.get()); break; - case 4: ::new (static_cast(data)) T5(other.get()); break; - case 5: ::new (static_cast(data)) T6(other.get()); break; - case 6: ::new (static_cast(data)) T7(other.get()); break; - case 7: ::new (static_cast(data)) T8(other.get()); break; - default: break; - } - - type_id = other.type_id; - } - -#if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && !defined(ETL_VARIANT_FORCE_CPP03) - //************************************************************************* - /// Emplace with variadic constructor parameters. - //************************************************************************* - template - T& emplace(Args&&... args) - { - ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); - - destruct_current(); - ::new (static_cast(data)) T(etl::forward(args)...); - type_id = Type_Id_Lookup::type_id; - - return *static_cast(data); - } +#if 1 //ETL_USE_LEGACY_VARIANT + #include "private/variant_legacy.h" #else - //*************************************************************************** - /// Emplace with one constructor parameter. - //*************************************************************************** - template - T& emplace(const TP1& value1) - { - ETL_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) - { - ETL_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) - { - ETL_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) - { - ETL_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); - } + #include "private/variant_new.h" #endif - //*************************************************************************** - /// Assignment operator for T1 type. - ///\param value The value to assign. - //*************************************************************************** - template - variant& operator =(const T& value) - { - ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); - - destruct_current(); - ::new (static_cast(data)) T(value); - type_id = Type_Id_Lookup::type_id; - - return *this; - } - - //*************************************************************************** - /// Assignment operator for variant type. - ///\param other The variant to assign. - //*************************************************************************** - variant& operator =(const variant& other) - { - if (this != &other) - { - destruct_current(); - - switch (other.type_id) - { - case 0: ::new (static_cast(data)) T1(other.get()); break; - case 1: ::new (static_cast(data)) T2(other.get()); break; - case 2: ::new (static_cast(data)) T3(other.get()); break; - case 3: ::new (static_cast(data)) T4(other.get()); break; - case 4: ::new (static_cast(data)) T5(other.get()); break; - case 5: ::new (static_cast(data)) T6(other.get()); break; - case 6: ::new (static_cast(data)) T7(other.get()); break; - case 7: ::new (static_cast(data)) T8(other.get()); break; - default: break; - } - - type_id = other.type_id; - } - - return *this; - } - - //*************************************************************************** - /// Checks if the type is the same as the current stored type. - /// For variants with the same type declarations. - ///\return true if the types are the same, otherwise false. - //*************************************************************************** - bool is_same_type(const variant& other) const - { - return type_id == other.type_id; - } - - //*************************************************************************** - /// Checks if the type is the same as the current stored type. - /// For variants with differing declarations. - ///\return true if the types are the same, otherwise false. - //*************************************************************************** - template - bool is_same_type(const variant& other) const - { - bool is_same = false; - - switch (other.type_id) - { - case 0: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 1: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 2: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 3: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 4: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 5: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 6: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 7: is_same = (type_id == Type_Id_Lookup::type_id); break; - default: break; - } - - return is_same; - } - - //*************************************************************************** - /// Calls the supplied reader instance. - /// The 'read' function appropriate to the current type is called with the stored value. - //*************************************************************************** - void call(reader& r) - { - switch (type_id) - { - case 0: r.read(static_cast(data)); break; - case 1: r.read(static_cast(data)); break; - case 2: r.read(static_cast(data)); break; - case 3: r.read(static_cast(data)); break; - case 4: r.read(static_cast(data)); break; - case 5: r.read(static_cast(data)); break; - case 6: r.read(static_cast(data)); break; - case 7: r.read(static_cast(data)); break; - default: break; - } - } - - //*************************************************************************** - /// Checks whether a valid value is currently stored. - ///\return true if the value is valid, otherwise false. - //*************************************************************************** - bool is_valid() const - { - return type_id != UNSUPPORTED_TYPE_ID; - } - - //*************************************************************************** - /// Checks to see if the type currently stored is the same as that specified in the template parameter. - ///\return true if it is the specified type, otherwise false. - //*************************************************************************** - template - bool is_type() const - { - return type_id == Type_Id_Lookup::type_id; - } - - //*************************************************************************** - /// Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID - //*************************************************************************** - size_t index() const - { - return type_id; - } - - //*************************************************************************** - /// Clears the value to 'no valid stored value'. - //*************************************************************************** - void clear() - { - destruct_current(); - } - - //*************************************************************************** - /// Gets the value stored as the specified template type. - /// Throws a variant_incorrect_type_exception if the actual type is not that specified. - ///\return A reference to the value. - //*************************************************************************** - template - T& get() - { - ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); - ETL_ASSERT(is_type(), ETL_ERROR(variant_incorrect_type_exception)); - - return static_cast(data); - } - - //*************************************************************************** - /// Gets the value stored as the specified template type. - /// Throws a variant_incorrect_type_exception if the actual type is not that specified. - ///\return A const reference to the value. - //*************************************************************************** - template - const T& get() const - { - ETL_STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); - ETL_ASSERT(is_type(), ETL_ERROR(variant_incorrect_type_exception)); - - return static_cast(data); - } - - //*************************************************************************** - /// Gets the value stored as the specified template type. - ///\return A reference to the value. - //*************************************************************************** - template - TBase& upcast() - { - return *upcast_functor()(data, type_id); - } - - //*************************************************************************** - /// Gets the value stored as the specified template type. - ///\return A const reference to the value. - //*************************************************************************** - template - const TBase& upcast() const - { - return *upcast_functor()(data, type_id); - } - - //*************************************************************************** - /// Conversion operators for each type. - //*************************************************************************** - operator T1&() { return get(); } - operator T2&() { return get(); } - operator T3&() { return get(); } - operator T4&() { return get(); } - operator T5&() { return get(); } - operator T6&() { return get(); } - operator T7&() { return get(); } - operator T8&() { return get(); } - - //*************************************************************************** - /// Checks if the template type is supported by the implementation of variant.. - ///\return true if the type is supported, otherwise false. - //*************************************************************************** - template - static bool is_supported_type() - { - return Type_Is_Supported::value; - } - - private: - - //*************************************************************************** - /// Destruct the current occupant of the variant. - //*************************************************************************** - void destruct_current() - { - switch (type_id) - { - case 0: { static_cast(data)->~T1(); break; } - case 1: { static_cast(data)->~T2(); break; } - case 2: { static_cast(data)->~T3(); break; } - case 3: { static_cast(data)->~T4(); break; } - case 4: { static_cast(data)->~T5(); break; } - case 5: { static_cast(data)->~T6(); break; } - case 6: { static_cast(data)->~T7(); break; } - case 7: { static_cast(data)->~T8(); break; } - default: { break; } - } - - type_id = UNSUPPORTED_TYPE_ID; - } - - //************************************************************************* - //**** Up-cast functors *************************************************** - //************************************************************************* - - //************************************************************************* - /// Base upcast_functor for eight types. - //************************************************************************* - template - class upcast_functor - { - public: - - TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - case 3: return reinterpret_cast(p_data); - case 4: return reinterpret_cast(p_data); - case 5: return reinterpret_cast(p_data); - case 6: return reinterpret_cast(p_data); - case 7: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - - const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - case 3: return reinterpret_cast(p_data); - case 4: return reinterpret_cast(p_data); - case 5: return reinterpret_cast(p_data); - case 6: return reinterpret_cast(p_data); - case 7: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - }; - - //************************************************************************* - /// Upcast_functor for seven types. - //************************************************************************* - template - class upcast_functor - { - public: - - TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - case 3: return reinterpret_cast(p_data); - case 4: return reinterpret_cast(p_data); - case 5: return reinterpret_cast(p_data); - case 6: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - - const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - case 3: return reinterpret_cast(p_data); - case 4: return reinterpret_cast(p_data); - case 5: return reinterpret_cast(p_data); - case 6: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - }; - - //************************************************************************* - /// Upcast_functor for six types. - //************************************************************************* - template - class upcast_functor - { - public: - - TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - case 3: return reinterpret_cast(p_data); - case 4: return reinterpret_cast(p_data); - case 5: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - - const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - case 3: return reinterpret_cast(p_data); - case 4: return reinterpret_cast(p_data); - case 5: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - }; - - //************************************************************************* - /// Upcast_functor for five types. - //************************************************************************* - template - class upcast_functor - { - public: - - TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - case 3: return reinterpret_cast(p_data); - case 4: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - - const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - case 3: return reinterpret_cast(p_data); - case 4: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - }; - - //************************************************************************* - /// Upcast_functor for four types. - //************************************************************************* - template - class upcast_functor - { - public: - - TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - case 3: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - - const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - case 3: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - }; - - //************************************************************************* - /// Upcast_functor for three types. - //************************************************************************* - template - class upcast_functor - { - public: - - TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - - const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - case 2: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - }; - - //************************************************************************* - /// Upcast_functor for two types. - //************************************************************************* - template - class upcast_functor - { - public: - - TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - - const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - case 1: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - }; - - //************************************************************************* - /// Upcast_functor for one type. - //************************************************************************* - template - class upcast_functor - { - public: - - TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - - const TBase* operator()(uint_least8_t* p_data, uint_least8_t typeId) const - { - switch (typeId) - { - case 0: return reinterpret_cast(p_data); - default: return reinterpret_cast(0); - } - } - }; - - //*************************************************************************** - /// The internal storage. - /// Aligned on a suitable boundary, which should be good for all types. - //*************************************************************************** - typename etl::aligned_storage::type data; - - //*************************************************************************** - /// The id of the current stored type. - //*************************************************************************** - type_id_t type_id; - }; -} - #endif diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index 80c7a26d..1cea32c9 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -1353,6 +1353,8 @@ + + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index 8b11f5cf..04825358 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -1101,6 +1101,12 @@ ETL\Frameworks + + ETL\Private + + + ETL\Private +