From 67c19bb0dcf2c9a758ebc13fdecbe93eb9c60c62 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 23 May 2021 20:37:29 +0100 Subject: [PATCH] Fold expression experiment --- include/etl/private/variant_new.h | 96 +++++++++++++++++++++++++++++-- test/test_variant_new.cpp | 38 +++++++++++- 2 files changed, 128 insertions(+), 6 deletions(-) diff --git a/include/etl/private/variant_new.h b/include/etl/private/variant_new.h index 97f918df..487cd945 100644 --- a/include/etl/private/variant_new.h +++ b/include/etl/private/variant_new.h @@ -7,7 +7,7 @@ Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com -Copyright(c) 2014 jwellbelove +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 @@ -43,11 +43,56 @@ SOFTWARE. #include "../parameter_pack.h" #include "../placement_new.h" +#include + #if defined(ETL_COMPILER_KEIL) #pragma diag_suppress 940 #pragma diag_suppress 111 #endif +namespace etl +{ + //template + //class integer_sequence + //{ + //public: + // + // ETL_STATIC_ASSERT(etl::is_integral::value, "Integral types only"); + + // typedef T value_type; + // + // static ETL_CONSTEXPR size_t size() ETL_NOEXCEPT + // { + // return sizeof...(Integers); + // } + //}; + + //namespace private_integer_sequence + //{ + // template + // struct make_index_sequence; + + // template + // struct make_index_sequence> + // { + // typedef typename make_index_sequence>::type type; + // }; + + // template + // struct make_index_sequence<0, integer_sequence> + // { + // typedef integer_sequence type; + // }; + //} + + //template + //using make_index_sequence = typename private_integer_sequence::make_index_sequence>::type; + + //template + //using index_sequence = integer_sequence; +} + + //***************************************************************************** ///\defgroup variant variant /// A class that can contain one a several specified types in a type safe manner. @@ -68,6 +113,13 @@ namespace etl { }; + constexpr bool operator >(etl::monostate, etl::monostate) noexcept { return false; } + constexpr bool operator <(etl::monostate, etl::monostate) noexcept { return false; } + constexpr bool operator !=(etl::monostate, etl::monostate) noexcept { return false; } + constexpr bool operator <=(etl::monostate, etl::monostate) noexcept { return true; } + constexpr bool operator >=(etl::monostate, etl::monostate) noexcept { return true; } + constexpr bool operator ==(etl::monostate, etl::monostate) noexcept { return true; } + //*************************************************************************** /// Base exception for the variant class. ///\ingroup variant @@ -207,11 +259,11 @@ namespace etl { static_assert(etl::is_one_of::value, "Unsupported type"); - T temp(etl::forward(args)...); - operation(action_type::Destruct, data, nullptr); operation = do_operation; + + T temp(etl::forward(args)...); operation(action_type::Construct, data, &temp); type_id = etl::parameter_pack::index_of_type::value; @@ -312,6 +364,15 @@ namespace etl return static_cast(data); } + //*************************************************************************** + /// Do an operation determined by type. + //*************************************************************************** + template + void accept(TVisitor& visitor) + { + do_accept(visitor, std::make_index_sequence{}); + } + private: using operation_type = void(*)(action_type, void*, const void*); @@ -343,6 +404,32 @@ namespace etl } } + //*************************************************************************** + /// Loop through the types until a match is found. + //*************************************************************************** + template + void do_accept(TVisitor& visitor, std::index_sequence) + { + (attempt_visitor(visitor) || ...); + } + + //*************************************************************************** + /// Attempt to call a visitor. + //*************************************************************************** + template + bool attempt_visitor(TVisitor& visitor) + { + if (Index == index()) + { + visitor.visit(etl::get(*this)); + return true; + } + else + { + return false; + } + } + //*************************************************************************** /// Default operation. //*************************************************************************** @@ -401,7 +488,7 @@ namespace etl constexpr etl::variant_alternative_t>& get(etl::variant& v) { - static_assert(Index < sizeof...(TTypes), "Index out of range"); + //static_assert(Index < sizeof...(TTypes), "Index out of range"); ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception)); using type = etl::variant_alternative_t>; @@ -559,5 +646,4 @@ namespace etl : etl::integral_constant::value> { }; - } diff --git a/test/test_variant_new.cpp b/test/test_variant_new.cpp index f0516e55..700780f8 100644 --- a/test/test_variant_new.cpp +++ b/test/test_variant_new.cpp @@ -5,7 +5,7 @@ Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com -Copyright(c) 2014 jwellbelove +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 @@ -29,6 +29,7 @@ SOFTWARE. #include "unit_test_framework.h" #include "etl/private/variant_new.h" +#include "etl/visitor.h" #include #include @@ -395,5 +396,40 @@ namespace D1 db = etl::move(etl::get(variant)); } + + //************************************************************************* + TEST(test_variant_visitor) + { + struct Visitor : public etl::visitor + { + void visit(char& c) + { + + } + + void visit(int& i) + { + + } + + void visit(std::string& s) + { + + } + }; + + Visitor visitor; + + test_variant_3 variant; + + variant = char(1); + variant.accept(visitor); + + variant = int(2); + variant.accept(visitor); + + variant = std::string("3"); + variant.accept(visitor); + } }; }