From 0bfc97a914c4f335f3f16d498cb5bad1ac6af6a0 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 19 May 2020 20:12:12 +0100 Subject: [PATCH] Variadic versions of etl::type_id_lookup and etl::type_type_lookup for C++11 and above. --- .gitignore | 1 + .../etl/generators/type_lookup_generator.h | 147 +++++ .../etl/generators/type_select_generator.h | 42 ++ .../etl/generators/type_traits_generator.h | 61 +++ include/etl/iterator.h | 2 +- .../determine_compiler_language_support.h | 4 +- include/etl/type_lookup.h | 147 +++++ include/etl/type_select.h | 42 ++ include/etl/variant.h | 29 +- include/etl/variant_new.h | 509 ++++++++++++++++++ include/etl/version.h | 4 +- library.json | 2 +- library.properties | 2 +- support/Release notes.txt | 4 + test/etl_profile.h | 1 + test/test_delegate.cpp | 52 +- test/test_message_packet.cpp | 2 + 17 files changed, 1003 insertions(+), 48 deletions(-) create mode 100644 include/etl/variant_new.h diff --git a/.gitignore b/.gitignore index 607eebc2..b5c756a6 100644 --- a/.gitignore +++ b/.gitignore @@ -254,3 +254,4 @@ unittest-cpp *.opendb build-test-Desktop_x86_windows_msvc2017_pe_32bit-Debug test/Logs +build-test-Desktop_x86_windows_msvc2019_pe_32bit-Debug diff --git a/include/etl/generators/type_lookup_generator.h b/include/etl/generators/type_lookup_generator.h index 1e5a785f..845d2816 100644 --- a/include/etl/generators/type_lookup_generator.h +++ b/include/etl/generators/type_lookup_generator.h @@ -34,6 +34,7 @@ SOFTWARE. #include "platform.h" #include "type_traits.h" #include "static_assert.h" +#include "integral_limits.h" #include "null_type.h" #undef ETL_FILE @@ -85,6 +86,150 @@ namespace etl typedef T2 type2; }; +#if ETL_CPP11_SUPPORTED && !defined(ETL_TYPE_SELECT_FORCE_CPP03) + //*************************************************************************** + // type_id_lookup + //*************************************************************************** + template + struct type_id_lookup + { + private: + + // The type for no match. + struct nulltype {}; + + // For N type pairs. + template + struct type_from_id_helper + { + using type = typename etl::conditional::type>::type; + }; + + // Specialisation for 1 type pair. + template + struct type_from_id_helper + { + using type = typename etl::conditional::type; + }; + + public: + + //************************************ + // type_from_id + //************************************ + template + struct type_from_id + { + using type = typename type_from_id_helper::type; + + static_assert(!(etl::is_same::value), "Invalid id"); + }; + + template + using type_from_id_t = typename type_from_id::type; + + private: + + static constexpr size_t UNKNOWN = etl::integral_limits::max; + + // For N type pairs. + template + struct id_from_type_helper + { + static constexpr size_t value = etl::is_same::value ? T1::ID : id_from_type_helper::value; + }; + + // Specialisation for 1 type pair. + template + struct id_from_type_helper + { + static constexpr size_t value = etl::is_same::value ? T1::ID : UNKNOWN; + }; + + public: + + //************************************ + // id_from_type + //************************************ + template + struct id_from_type + { + static constexpr size_t value = id_from_type_helper::value; + + static_assert(value != UNKNOWN, "Invalid type"); + }; + +#if ETL_CPP17_SUPPORTED + template + static constexpr size_t id_from_type_v = id_from_type::value; +#endif + + //************************************ + template + static unsigned int get_id_from_type(const T&) + { + return get_id_from_type(); + } + + //************************************ + template + static unsigned int get_id_from_type() + { + return id_from_type::value; + } + }; + + //*************************************************************************** + // type_type_lookup + //*************************************************************************** + template + class type_type_lookup + { + private: + + // The type for no match. + struct nulltype {}; + + template + struct type_from_type_helper + { + using type = typename etl::conditional::value, + typename T1::type2, + typename type_from_type_helper::type>::type; + }; + + template + struct type_from_type_helper + { + using type = typename etl::conditional::value, + typename T1::type2, + nulltype>::type; + }; + + public: + + template + class type_from_type + { + public: + + // The matched type or nulltype + using type = typename type_from_type_helper::type; + + static_assert(!etl::is_same::value, "Type match not found"); + }; + + // Template alias. + template + using TypeFromType_t = typename type_from_type::type; + }; + +#else + /*[[[cog import cog cog.outl("//***************************************************************************") @@ -188,6 +333,8 @@ namespace etl cog.outl("};") ]]]*/ /*[[[end]]]*/ + +#endif } #undef ETL_FILE diff --git a/include/etl/generators/type_select_generator.h b/include/etl/generators/type_select_generator.h index 70880f9c..17dd4a00 100644 --- a/include/etl/generators/type_select_generator.h +++ b/include/etl/generators/type_select_generator.h @@ -59,6 +59,47 @@ cog.outl("//******************************************************************** namespace etl { +#if ETL_CPP11_SUPPORTED && !defined(ETL_TYPE_SELECT_FORCE_CPP03) + //*************************************************************************** + // Variadic version. + //*************************************************************************** + template + struct type_select + { + private: + + //*********************************** + template + struct type_select_helper + { + using type = typename etl::conditional::type>::type; + }; + + //*********************************** + template + struct type_select_helper + { + using type = T1; + }; + + public: + + template + struct select + { + static_assert(ID < sizeof...(TTypes), "Illegal type_select::select index"); + + using type = typename type_select_helper::type; + }; + + template + using select_t = typename select::type; + }; + +#else + /*[[[cog import cog cog.outl("//***************************************************************************") @@ -127,6 +168,7 @@ namespace etl cog.outl("};") ]]]*/ /*[[[end]]]*/ +#endif } #undef ETL_FILE diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index bc865f6a..c171e35b 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -116,6 +116,30 @@ namespace etl using bool_constant = integral_constant; #endif + //*************************************************************************** + /// bool_constant + template + struct bool_constant :etl::integral_constant + { + }; + +#if ETL_CPP17_SUPPORTED + template + inline constexpr bool bool_constant_v = bool_constant::value; +#endif + + //*************************************************************************** + /// negation + template + struct negation : etl::bool_constant + { + }; + +#if ETL_CPP17_SUPPORTED + template + inline constexpr bool negation_v = negation::value; +#endif + //*************************************************************************** /// remove_reference template struct remove_reference { typedef T type; }; @@ -1533,6 +1557,43 @@ namespace etl template inline constexpr size_t size_of_v = etl::size_of::value; #endif + + //*************************************************************************** + /// index_of + namespace private_type_traits + { + template + struct index_of_helper; + + template + struct index_of_helper + { + enum + { + value = etl::is_same::value ? 1 : 1 + index_of_helper::value + }; + }; + + template + struct index_of_helper + { + enum + { + value = 1 + }; + }; + } + + template + struct index_of + { + static ETL_CONST_OR_CONSTEXPR size_t npos = -1; + + enum + { + value = etl::is_one_of::value ? private_type_traits::index_of_helper::value - 1 : npos + }; + }; } #endif // ETL_TYPE_TRAITS_INCLUDED diff --git a/include/etl/iterator.h b/include/etl/iterator.h index 73dd9d2e..6e323d9a 100644 --- a/include/etl/iterator.h +++ b/include/etl/iterator.h @@ -35,7 +35,7 @@ SOFTWARE. #include "type_traits.h" #include "utility.h" -#if ETL_USING_STL +#if ETL_USING_STL || defined(ETL_IN_UNIT_TEST) #include #endif diff --git a/include/etl/profiles/determine_compiler_language_support.h b/include/etl/profiles/determine_compiler_language_support.h index 84b212eb..c6db0fdc 100644 --- a/include/etl/profiles/determine_compiler_language_support.h +++ b/include/etl/profiles/determine_compiler_language_support.h @@ -75,9 +75,7 @@ SOFTWARE. // NAN not defined or Rowley CrossWorks #if !defined(NAN) || defined(__CROSSWORKS_ARM) || defined(ETL_COMPILER_ARM5) - #if !defined(ETL_NO_CPP_NAN_SUPPORT) - #define ETL_NO_CPP_NAN_SUPPORT - #endif + #define ETL_NO_CPP_NAN_SUPPORT #endif #endif diff --git a/include/etl/type_lookup.h b/include/etl/type_lookup.h index 4d5b780b..c2c46ae6 100644 --- a/include/etl/type_lookup.h +++ b/include/etl/type_lookup.h @@ -34,6 +34,7 @@ SOFTWARE. #include "platform.h" #include "type_traits.h" #include "static_assert.h" +#include "integral_limits.h" #include "null_type.h" #undef ETL_FILE @@ -73,6 +74,150 @@ namespace etl typedef T2 type2; }; +#if ETL_CPP11_SUPPORTED && !defined(ETL_TYPE_SELECT_FORCE_CPP03) + //*************************************************************************** + // type_id_lookup + //*************************************************************************** + template + struct type_id_lookup + { + private: + + // The type for no match. + struct nulltype {}; + + // For N type pairs. + template + struct type_from_id_helper + { + using type = typename etl::conditional::type>::type; + }; + + // Specialisation for 1 type pair. + template + struct type_from_id_helper + { + using type = typename etl::conditional::type; + }; + + public: + + //************************************ + // type_from_id + //************************************ + template + struct type_from_id + { + using type = typename type_from_id_helper::type; + + static_assert(!(etl::is_same::value), "Invalid id"); + }; + + template + using type_from_id_t = typename type_from_id::type; + + private: + + static constexpr size_t UNKNOWN = etl::integral_limits::max; + + // For N type pairs. + template + struct id_from_type_helper + { + static constexpr size_t value = etl::is_same::value ? T1::ID : id_from_type_helper::value; + }; + + // Specialisation for 1 type pair. + template + struct id_from_type_helper + { + static constexpr size_t value = etl::is_same::value ? T1::ID : UNKNOWN; + }; + + public: + + //************************************ + // id_from_type + //************************************ + template + struct id_from_type + { + static constexpr size_t value = id_from_type_helper::value; + + static_assert(value != UNKNOWN, "Invalid type"); + }; + +#if ETL_CPP17_SUPPORTED + template + static constexpr size_t id_from_type_v = id_from_type::value; +#endif + + //************************************ + template + static unsigned int get_id_from_type(const T&) + { + return get_id_from_type(); + } + + //************************************ + template + static unsigned int get_id_from_type() + { + return id_from_type::value; + } + }; + + //*************************************************************************** + // type_type_lookup + //*************************************************************************** + template + class type_type_lookup + { + private: + + // The type for no match. + struct nulltype {}; + + template + struct type_from_type_helper + { + using type = typename etl::conditional::value, + typename T1::type2, + typename type_from_type_helper::type>::type; + }; + + template + struct type_from_type_helper + { + using type = typename etl::conditional::value, + typename T1::type2, + nulltype>::type; + }; + + public: + + template + class type_from_type + { + public: + + // The matched type or nulltype + using type = typename type_from_type_helper::type; + + static_assert(!etl::is_same::value, "Type match not found"); + }; + + // Template alias. + template + using TypeFromType_t = typename type_from_type::type; + }; + +#else + //*************************************************************************** // For 16 types. //*************************************************************************** @@ -224,6 +369,8 @@ namespace etl ETL_STATIC_ASSERT(!(etl::is_same, type>::value), "Invalid type"); }; }; + +#endif } #undef ETL_FILE diff --git a/include/etl/type_select.h b/include/etl/type_select.h index 894b642d..9d34f388 100644 --- a/include/etl/type_select.h +++ b/include/etl/type_select.h @@ -47,6 +47,47 @@ SOFTWARE. namespace etl { +#if ETL_CPP11_SUPPORTED && !defined(ETL_TYPE_SELECT_FORCE_CPP03) + //*************************************************************************** + // Variadic version. + //*************************************************************************** + template + struct type_select + { + private: + + //*********************************** + template + struct type_select_helper + { + using type = typename etl::conditional::type>::type; + }; + + //*********************************** + template + struct type_select_helper + { + using type = T1; + }; + + public: + + template + struct select + { + static_assert(ID < sizeof...(TTypes), "Illegal type_select::select index"); + + using type = typename type_select_helper::type; + }; + + template + using select_t = typename select::type; + }; + +#else + //*************************************************************************** // For 16 types. //*************************************************************************** @@ -583,6 +624,7 @@ namespace etl ETL_STATIC_ASSERT(ID < 1, "Invalid ID"); }; }; +#endif } #undef ETL_FILE diff --git a/include/etl/variant.h b/include/etl/variant.h index dedaf8ab..8909e754 100644 --- a/include/etl/variant.h +++ b/include/etl/variant.h @@ -45,6 +45,7 @@ SOFTWARE. #include "static_assert.h" #include "alignment.h" #include "error_handler.h" +#include "null_type.h" #if defined(ETL_COMPILER_KEIL) #pragma diag_suppress 940 @@ -106,13 +107,13 @@ namespace etl ///\ingroup variant //*************************************************************************** template , - typename T3 = private_variant::no_type<3>, - typename T4 = private_variant::no_type<4>, - typename T5 = private_variant::no_type<5>, - typename T6 = private_variant::no_type<6>, - typename T7 = private_variant::no_type<7>, - typename T8 = private_variant::no_type<8> > + typename T2 = etl::null_type<2>, + 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: @@ -151,13 +152,13 @@ namespace etl //*************************************************************************** /// Short form of no_type placeholders. //*************************************************************************** - typedef private_variant::no_type<2> no_type2; - typedef private_variant::no_type<3> no_type3; - typedef private_variant::no_type<4> no_type4; - typedef private_variant::no_type<5> no_type5; - typedef private_variant::no_type<6> no_type6; - typedef private_variant::no_type<7> no_type7; - typedef private_variant::no_type<8> no_type8; + 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. diff --git a/include/etl/variant_new.h b/include/etl/variant_new.h new file mode 100644 index 00000000..503aa98d --- /dev/null +++ b/include/etl/variant_new.h @@ -0,0 +1,509 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2020 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. +******************************************************************************/ + +#ifndef ETL_VARIANT_NEW_INCLUDED +#define ETL_VARIANT_NEW_INCLUDED + +#include + +#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" + +#if defined(ETL_COMPILER_KEIL) + #pragma diag_suppress 940 + #pragma diag_suppress 111 +#endif + +#undef ETL_FILE +#define ETL_FILE "24" + +#if ETL_CPP11_SUPPORTED + +//***************************************************************************** +///\defgroup variant variant +/// A class that can contain one a several specified types in a type safe manner. +///\ingroup containers +//***************************************************************************** + +namespace etl +{ + //*************************************************************************** + /// 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_FILE"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 + class variant + { + public: + + //*************************************************************************** + /// The id a unsupported types. + //*************************************************************************** + static ETL_CONST_OR_CONSTEXPR size_t npos = -1; + + 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; + + public: + + //*************************************************************************** + /// Destructor. + //*************************************************************************** + ~variant() + { + destruct_current(); + } + + //*************************************************************************** + /// 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(etl::index_of::value != etl::index_of::npos, "Unsupported type"); + + ::new (static_cast(data)) T(value); + type_id = etl::index_of::value; + } + + //*************************************************************************** + /// 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; + } + + constexpr size_t NUMBER_OF_VARIANTS = sizeof...(TVariants); + + //*************************************************************************** + /// 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 + +#undef ETL_FILE + +#endif diff --git a/include/etl/version.h b/include/etl/version.h index 900938da..e52d6e29 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -38,8 +38,8 @@ SOFTWARE. ///\ingroup utilities #define ETL_VERSION_MAJOR 18 -#define ETL_VERSION_MINOR 1 -#define ETL_VERSION_PATCH 3 +#define ETL_VERSION_MINOR 2 +#define ETL_VERSION_PATCH 0 #define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) "." ETL_STRINGIFY(ETL_VERSION_MINOR) "." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_STRINGIFY(ETL_VERSION_MAJOR) L"." ETL_STRINGIFY(ETL_VERSION_MINOR) L"." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_U16 ETL_STRINGIFY(ETL_VERSION_MAJOR) u"." ETL_STRINGIFY(ETL_VERSION_MINOR) u"." ETL_STRINGIFY(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index c8993b2c..e6e741bb 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library", - "version": "18.1.3", + "version": "18.2.0", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index 320ca1ae..a2c2b42f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=18.1.3 +version=18.2.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/support/Release notes.txt b/support/Release notes.txt index b79896f5..3db2bbef 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +18.2.0 +Variadic versions of etl::type_id_lookup and etl::type_type_lookup for C++11 and above. + =============================================================================== 18.1.3 Added CircleCI yml file for master branch diff --git a/test/etl_profile.h b/test/etl_profile.h index 141e958e..64f6f7d4 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -91,6 +91,7 @@ SOFTWARE. //#define ETL_QUEUE_LOCKED_FORCE_CPP03 //#define ETL_OPTIONAL_FORCE_CPP03 //#define ETL_LARGEST_TYPE_FORCE_CPP03 +//#define ETL_TYPE_SELECT_FORCE_CPP03 #if defined(ETL_NO_STL) #define ETL_TIMER_SEMAPHORE_TYPE uint32_t diff --git a/test/test_delegate.cpp b/test/test_delegate.cpp index aa69555e..91f7aaae 100644 --- a/test/test_delegate.cpp +++ b/test/test_delegate.cpp @@ -70,7 +70,7 @@ namespace void free_reference(const Data& data, int j) { function_called = true; - parameter_correct = (data.d == VALUE1) && (j = VALUE2); + parameter_correct = (data.d == VALUE1) && (j == VALUE2); } //***************************************************************************** @@ -185,7 +185,7 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_free_void) { - etl::delegate d = etl::delegate::create(); + auto d = etl::delegate::create(); d(); @@ -195,7 +195,7 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_free_int) { - etl::delegate d = etl::delegate::create(); + auto d = etl::delegate::create(); d(VALUE1, VALUE2); @@ -256,7 +256,7 @@ namespace { Test test; - etl::delegate d = etl::delegate::create(test); + auto d = etl::delegate::create(test); d(); @@ -279,7 +279,7 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_member_operator_void_compile_time) { - etl::delegate d = etl::delegate::create(); + auto d = etl::delegate::create(); d(); @@ -289,7 +289,7 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_member_operator_void_compile_time_const) { - etl::delegate d = etl::delegate::create(); + auto d = etl::delegate::create(); d(); @@ -316,7 +316,7 @@ namespace { Test test; - etl::delegate d = etl::delegate::create(test); + auto d = etl::delegate::create(test); d(); @@ -328,7 +328,7 @@ namespace { const Test test; - etl::delegate d = etl::delegate::create(test); + auto d = etl::delegate::create(test); d(); @@ -340,7 +340,7 @@ namespace { Test test; - etl::delegate d = etl::delegate::create(test); + auto d = etl::delegate::create(test); d(VALUE1, VALUE2); @@ -353,7 +353,7 @@ namespace { const Test test; - etl::delegate d = etl::delegate::create(test); + auto d = etl::delegate::create(test); d(VALUE1, VALUE2); @@ -365,7 +365,7 @@ namespace TEST_FIXTURE(SetupFixture, test_member_reference) { Test test; - etl::delegate d = etl::delegate::create(test); + auto d = etl::delegate::create(test); Data data; data.d = VALUE1; @@ -380,7 +380,7 @@ namespace TEST_FIXTURE(SetupFixture, test_member_reference_const) { const Test test; - etl::delegate d = etl::delegate::create(test); + auto d = etl::delegate::create(test); Data data; data.d = VALUE1; @@ -394,7 +394,7 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_member_static) { - etl::delegate d = etl::delegate::create(); + auto d = etl::delegate::create(); Data data; data.d = VALUE1; @@ -409,7 +409,7 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_member_void_compile_time) { - etl::delegate d = etl::delegate::create(); + auto d = etl::delegate::create(); d(); @@ -419,7 +419,7 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_member_void_const_compile_time) { - etl::delegate d = etl::delegate::create(); + auto d = etl::delegate::create(); d(); @@ -429,7 +429,7 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_member_int_compile_time) { - etl::delegate d = etl::delegate::create(); + auto d = etl::delegate::create(); d(VALUE1, VALUE2); @@ -440,7 +440,7 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_member_int_const_compile_time) { - etl::delegate d = etl::delegate::create(); + auto d = etl::delegate::create(); d(VALUE1, VALUE2); @@ -451,7 +451,7 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_member_reference_compile_time) { - etl::delegate d = etl::delegate::create(); + auto d = etl::delegate::create(); Data data; data.d = VALUE1; @@ -465,7 +465,7 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_member_reference_const_compile_time) { - etl::delegate d = etl::delegate::create(); + auto d = etl::delegate::create(); Data data; data.d = VALUE1; @@ -482,8 +482,8 @@ namespace { Test test; - etl::delegate d1 = etl::delegate::create(test); - etl::delegate d2(d1); + auto d1 = etl::delegate::create(test); + auto d2(d1); d2(VALUE1, VALUE2); @@ -496,7 +496,7 @@ namespace { Test test; - etl::delegate d1 = etl::delegate::create(test); + auto d1 = etl::delegate::create(test); etl::delegate d2; d2 = d1; @@ -512,8 +512,8 @@ namespace { Test test; - etl::delegate d1 = etl::delegate::create(test); - etl::delegate d2 = d1; + auto d1 = etl::delegate::create(test); + auto d2 = d1; CHECK(d1 == d2); } @@ -523,8 +523,8 @@ namespace { Test test; - etl::delegate d1 = etl::delegate::create(test); - etl::delegate d2 = etl::delegate::create(test);; + auto d1 = etl::delegate::create(test); + auto d2 = etl::delegate::create(test);; CHECK(d1 != d2); } diff --git a/test/test_message_packet.cpp b/test/test_message_packet.cpp index 54e90d5d..6ed82775 100644 --- a/test/test_message_packet.cpp +++ b/test/test_message_packet.cpp @@ -162,6 +162,7 @@ namespace x = other.x; moved = false; copied = true; + return *this; } Message3& operator =(Message3&& other) @@ -169,6 +170,7 @@ namespace x = other.x; moved = true; copied = false; + return *this; } std::string x;