From 2025e6ff9bc17f75ead76e2671085c1d16281741 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 22 Jun 2021 10:43:39 +0100 Subject: [PATCH] Latest updates --- include/etl/overload.h | 85 +++++++++++++++++++++++++++++++ include/etl/private/variant_new.h | 84 +++++++++++++++++++++--------- test/etl_profile.h | 2 + test/test_variant_new.cpp | 72 ++++++++++++++++++++++++-- test/vs2019/etl.vcxproj | 3 +- test/vs2019/etl.vcxproj.filters | 11 ++-- 6 files changed, 223 insertions(+), 34 deletions(-) create mode 100644 include/etl/overload.h diff --git a/include/etl/overload.h b/include/etl/overload.h new file mode 100644 index 00000000..2fc7640b --- /dev/null +++ b/include/etl/overload.h @@ -0,0 +1,85 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2021 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_OVERLOAD_INCLUDED +#define ETL_OVERLOAD_INCLUDED + +#include "platform.h" + +namespace etl +{ +#if ETL_CPP11_SUPPORTED + #if ETL_CPP17_SUPPORTED && !defined(ETL_OVERLOAD_FORCE_CPP11) + //************************************************************************* + /// Variadic template definition of overload. + //************************************************************************* + template + struct overload : Ts... + { + using Ts::operator()...; + }; + + //************************************************************************* + /// Template deduction guide. + //************************************************************************* + template overload(Ts...)->overload; + +#else + //************************************************************************* + /// Variadic template definition of overload. + //************************************************************************* + template + struct overload : T, overload + { + using T::operator(); + using overload::operator(); + }; + + //************************************************************************* + /// Template specialisation of overload for one type. + //************************************************************************* + template struct overload : T + { + using T::operator(); + }; +#endif + + //************************************************************************* + /// Make an overload. + //************************************************************************* + template + constexpr auto make_overload(T&&... t) + { + return overload{ etl::forward(t)... }; + } +} + +#endif +#endif diff --git a/include/etl/private/variant_new.h b/include/etl/private/variant_new.h index 487cd945..e11a6e32 100644 --- a/include/etl/private/variant_new.h +++ b/include/etl/private/variant_new.h @@ -42,6 +42,7 @@ SOFTWARE. #include "../error_handler.h" #include "../parameter_pack.h" #include "../placement_new.h" +#include "../visitor.h" #include @@ -205,7 +206,7 @@ namespace etl constexpr variant() : data() { - using type = typename etl::parameter_pack::type_from_index<0>::type; + using type = typename etl::parameter_pack::template type_from_index<0>::type; type temp; @@ -221,7 +222,7 @@ namespace etl constexpr variant(const T& value) : data() , operation(do_operation) - , type_id(etl::parameter_pack::index_of_type::value) + , type_id(etl::parameter_pack::template index_of_type::value) { static_assert(etl::is_one_of::value, "Unsupported type"); @@ -266,7 +267,7 @@ namespace etl T temp(etl::forward(args)...); operation(action_type::Construct, data, &temp); - type_id = etl::parameter_pack::index_of_type::value; + type_id = etl::parameter_pack::template index_of_type::value; return *static_cast(data); } @@ -285,7 +286,7 @@ namespace etl operation = do_operation; operation(action_type::Construct, data, &value); - type_id = etl::parameter_pack::index_of_type::value; + type_id = etl::parameter_pack::template index_of_type::value; return *this; } @@ -365,12 +366,21 @@ namespace etl } //*************************************************************************** - /// Do an operation determined by type. + /// Accept an etl::visitor. + //*************************************************************************** + template + void accept(etl::visitor& v) + { + do_accept(v, std::make_index_sequence{}); + } + + //*************************************************************************** + /// Accept a generic visitor. //*************************************************************************** template - void accept(TVisitor& visitor) + void operator()(TVisitor& v) { - do_accept(visitor, std::make_index_sequence{}); + do_operator(v, std::make_index_sequence{}); } private: @@ -430,6 +440,32 @@ namespace etl } } + //*************************************************************************** + /// Loop through the types until a match is found. + //*************************************************************************** + template + void do_operator(TVisitor& visitor, std::index_sequence) + { + (attempt_operator(visitor) || ...); + } + + //*************************************************************************** + /// Attempt to call a visitor. + //*************************************************************************** + template + bool attempt_operator(TVisitor& visitor) + { + if (Index == index()) + { + visitor(etl::get(*this)); + return true; + } + else + { + return false; + } + } + //*************************************************************************** /// Default operation. //*************************************************************************** @@ -455,7 +491,7 @@ namespace etl template constexpr bool holds_alternative(const etl::variant& v) noexcept { - constexpr size_t Index = etl::parameter_pack::index_of_type::value; + constexpr size_t Index = etl::parameter_pack::template index_of_type::value; return (Index == variant_npos) ? false : (v.index() == Index); } @@ -538,7 +574,7 @@ namespace etl template constexpr T& get(etl::variant& v) { - constexpr size_t Index = etl::parameter_pack::index_of_type::value; + constexpr size_t Index = etl::parameter_pack::template index_of_type::value; return get(v); } @@ -547,7 +583,7 @@ namespace etl template constexpr T&& get(etl::variant&& v) { - constexpr size_t Index = etl::parameter_pack::index_of_type::value; + constexpr size_t Index = etl::parameter_pack::template index_of_type::value; return get(v); } @@ -556,7 +592,7 @@ namespace etl template constexpr const T& get(const etl::variant& v) { - constexpr size_t Index = etl::parameter_pack::index_of_type::value; + constexpr size_t Index = etl::parameter_pack::template index_of_type::value; return get(v); } @@ -565,7 +601,7 @@ namespace etl template constexpr const T&& get(const etl::variant&& v) { - constexpr size_t Index = etl::parameter_pack::index_of_type::value; + constexpr size_t Index = etl::parameter_pack::template index_of_type::value; return get(v); } @@ -573,9 +609,9 @@ namespace etl //*************************************************************************** /// get_if //*************************************************************************** - template < size_t Index, class... Types > - constexpr etl::add_pointer_t>> - get_if(etl::variant* pv) noexcept + template < size_t Index, typename... TTypes > + constexpr etl::add_pointer_t>> + get_if(etl::variant* pv) noexcept { if ((pv != nullptr) && (pv->index() == Index)) { @@ -588,9 +624,9 @@ namespace etl } //*********************************** - template< size_t Index, class... Types > - constexpr etl::add_pointer_t>> - get_if(const etl::variant* pv) noexcept + template< size_t Index, typename... TTypes > + constexpr etl::add_pointer_t>> + get_if(const etl::variant* pv) noexcept { if ((pv != nullptr) && (pv->index() == Index)) { @@ -603,19 +639,19 @@ namespace etl } //*********************************** - template< class T, class... Types > - constexpr etl::add_pointer_t get_if(etl::variant* pv) noexcept + template< class T, typename... TTypes > + constexpr etl::add_pointer_t get_if(etl::variant* pv) noexcept { - constexpr size_t Index = etl::parameter_pack::index_of_type::value; + constexpr size_t Index = etl::parameter_pack::template index_of_type::value; return etl::get_if(pv); } //*********************************** - template< class T, class... Types > - constexpr etl::add_pointer_t get_if(const etl::variant* pv) noexcept + template< class T, typename... TTypes > + constexpr etl::add_pointer_t get_if(const etl::variant* pv) noexcept { - constexpr size_t Index = etl::parameter_pack::index_of_type::value; + constexpr size_t Index = etl::parameter_pack::template index_of_type::value; return etl::get_if(pv); } diff --git a/test/etl_profile.h b/test/etl_profile.h index c1652ae3..bbb0926b 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -98,6 +98,8 @@ SOFTWARE. #define ETL_MEM_CAST_FORCE_CPP03 #endif +#define ETL_OVERLOAD_FORCE_CPP11 + #if defined(ETL_NO_STL) #define ETL_TIMER_SEMAPHORE_TYPE uint32_t #endif diff --git a/test/test_variant_new.cpp b/test/test_variant_new.cpp index 700780f8..e19a74bc 100644 --- a/test/test_variant_new.cpp +++ b/test/test_variant_new.cpp @@ -35,6 +35,7 @@ SOFTWARE. #include #include #include +#include namespace { @@ -399,23 +400,34 @@ namespace //************************************************************************* TEST(test_variant_visitor) - { + { struct Visitor : public etl::visitor { + Visitor() + : result_c(0) + , result_i(0) + , result_s("") + { + } + void visit(char& c) { - + result_c = c; } void visit(int& i) { - + result_i = i; } void visit(std::string& s) { - + result_s = s; } + + char result_c; + int result_i; + std::string result_s; }; Visitor visitor; @@ -424,12 +436,64 @@ namespace variant = char(1); variant.accept(visitor); + CHECK_EQUAL(1, visitor.result_c); variant = int(2); variant.accept(visitor); + CHECK_EQUAL(2, visitor.result_i); variant = std::string("3"); variant.accept(visitor); + CHECK_EQUAL("3", visitor.result_s); + } + + //************************************************************************* + TEST(test_variant_operator_visit) + { + struct Visitor + { + Visitor() + : result_c(0) + , result_i(0) + , result_s("") + { + } + + void operator()(char& c) + { + result_c = c; + } + + void operator()(int& i) + { + result_i = i; + } + + void operator()(std::string& s) + { + result_s = s; + } + + char result_c; + int result_i; + std::string result_s; + }; + + Visitor visitor; + + test_variant_3 variant; + + variant = char(1); + variant(visitor); + CHECK_EQUAL(1, visitor.result_c); + + variant = int(2); + variant(visitor); + CHECK_EQUAL(2, visitor.result_i); + + variant = std::string("3"); + variant(visitor); + CHECK_EQUAL("3", visitor.result_s); } }; } diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index 3b3a491b..6eb9aa6f 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -1348,6 +1348,7 @@ + @@ -5033,4 +5034,4 @@ - + \ No newline at end of file diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index f617841b..db5c98e6 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -1112,11 +1112,12 @@ ETL\Utilities - - ETL\Private - - ETL\Private + + Header Files + + + ETL\Patterns ETL\Utilities @@ -2701,4 +2702,4 @@ Resource Files - + \ No newline at end of file