From 9e7807baa8d9fffe593f6d7b9ef394ccb7a06765 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 17 Oct 2020 12:06:12 +0100 Subject: Custom enummap type Starts down the constexpr route, removes some need for boost::multi_index --- slicer/slicer/enumMap.h | 66 ++++++++++++++++++++++++++++++++++++ slicer/slicer/modelPartsTypes.h | 4 +-- slicer/slicer/modelPartsTypes.impl.h | 33 ++++++------------ slicer/tool/parser.cpp | 20 +++++++---- 4 files changed, 91 insertions(+), 32 deletions(-) create mode 100644 slicer/slicer/enumMap.h diff --git a/slicer/slicer/enumMap.h b/slicer/slicer/enumMap.h new file mode 100644 index 0000000..98ecd04 --- /dev/null +++ b/slicer/slicer/enumMap.h @@ -0,0 +1,66 @@ +#ifndef SLICER_ENUM_MAP_H +#define SLICER_ENUM_MAP_H + +namespace Slicer { + enum class EnumMapKey { + Value, + Name, + }; + + template class EnumMap { + public: + struct Node { + E value; + std::string_view name; + const std::string * nameStr; + }; + + template + constexpr inline const Node * + find(const T & v) const + { + auto b = begin(); + const auto e = end(); + while (b != e) { + if constexpr (Key == EnumMapKey::Value) { + if (b->value == v) { + return b; + } + } + else if constexpr (Key == EnumMapKey::Name) { + if (b->name == v) { + return b; + } + } + ++b; + } + return nullptr; + } + + virtual constexpr const Node * begin() const = 0; + virtual constexpr const Node * end() const = 0; + }; + + template class EnumMapImpl : public EnumMap { + public: + using NodeType = typename EnumMap::Node; + template using Arr = std::array; + + constexpr const NodeType * + begin() const override + { + return arr.begin(); + } + + constexpr const NodeType * + end() const override + { + return arr.end(); + } + + inline constexpr EnumMapImpl(Arr a) : arr(std::move(a)) { } + const Arr arr; + }; +} + +#endif diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index 78eee3b..062d9c2 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -225,11 +225,11 @@ namespace Slicer { ModelPartType GetType() const override; static const ModelPartType type; }; + template class EnumMap; template class DLL_PUBLIC ModelPartForEnum : public ModelPartForEnumBase, protected ModelPartModel { public: using element_type = T; - class DLL_PRIVATE Enumerations; explicit ModelPartForEnum(T * s); @@ -240,7 +240,7 @@ namespace Slicer { bool GetValue(ValueTarget && s) override; static const Metadata metadata; - static const Enumerations enumerations; + static constexpr const EnumMap & enumerations(); DLL_PUBLIC static const std::string & lookup(T); DLL_PUBLIC static T lookup(const std::string_view &); }; diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 7efc02d..b79a141 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -2,6 +2,7 @@ #define SLICER_MODELPARTSTYPES_IMPL_H #include "common.h" +#include "enumMap.h" #include "modelPartsTypes.h" #include #include @@ -659,18 +660,6 @@ namespace Slicer { } // ModelPartForEnum - template using EnumPair = std::pair; - - template - class ModelPartForEnum::Enumerations : - public boost::multi_index_container, - boost::multi_index::indexed_by, const T, &EnumPair::first>>, - boost::multi_index::ordered_unique< - boost::multi_index::member, const std::string, &EnumPair::second>, - std::less<>>>> { - }; - template ModelPartForEnum::ModelPartForEnum(T * s) : ModelPartModel(s) { } template @@ -680,14 +669,12 @@ namespace Slicer { return metadata; } - template - inline const auto & - ModelPartForEnumLookup( - const typename ModelPartForEnum::Enumerations & enumerations, const V & val, R EnumPair::*rv) + template + inline const auto * + ModelPartForEnumLookup(const EnumMap & enumerations, const V & val) { - const auto & side = enumerations.template get(); - if (auto i = side.find(val); i != side.end()) { - return (*i).*rv; + if (auto i = enumerations.template find(val)) { + return i; } throw Ex(ExP(val), typeid(T).name()); } @@ -696,16 +683,16 @@ namespace Slicer { T ModelPartForEnum::lookup(const std::string_view & val) { - return ModelPartForEnumLookup<1, InvalidEnumerationSymbol, std::string, T>( - enumerations, val, &EnumPair::first); + return ModelPartForEnumLookup(enumerations(), val) + ->value; } template const std::string & ModelPartForEnum::lookup(T val) { - return ModelPartForEnumLookup<0, InvalidEnumerationValue, ::Ice::Int, T>( - enumerations, val, &EnumPair::second); + return *ModelPartForEnumLookup(enumerations(), val) + ->nameStr; } template diff --git a/slicer/tool/parser.cpp b/slicer/tool/parser.cpp index 5a1d626..5951d54 100644 --- a/slicer/tool/parser.cpp +++ b/slicer/tool/parser.cpp @@ -420,15 +420,21 @@ namespace Slicer { copyMetadata(e->getMetaData()); fprintbf(cpp, ";\n\n"); - fprintbf(cpp, - "template<> DLL_PUBLIC\nconst ModelPartForEnum< %s >::Enumerations\nModelPartForEnum< %s " - ">::enumerations([]() -> ModelPartForEnum< %s >::Enumerations\n", - e->scoped(), e->scoped(), e->scoped()); - fprintbf(cpp, "{\n\tModelPartForEnum< %s >::Enumerations e;\n", e->scoped()); + size_t en = 0; + for (const auto & ee : e->enumerators()) { + fprintbf(cpp, "\tconst std::string estr%d_%d { \"%s\" };\n", components, en++, ee->name()); + } + fprintbf(cpp, "constexpr const EnumMapImpl< %s, %d > enumerations%d {{{\n", e->scoped(), + e->enumerators().size(), components); + en = 0; for (const auto & ee : e->enumerators()) { - fprintbf(cpp, "\te.insert( { %s, \"%s\" } );\n", ee->scoped(), ee->name()); + fprintbf(cpp, "\t {%s, \"%s\", &estr%d_%d},\n", ee->scoped(), ee->name(), components, en++); } - fprintbf(cpp, "\treturn e;\n}());\n\n"); + fprintbf(cpp, "\t}}};\n"); + fprintbf(cpp, + "\ttemplate<> constexpr const EnumMap< %s > & ModelPartForEnum< %s >::enumerations() { return " + "enumerations%d; }\n", + e->scoped(), e->scoped(), components); auto name = metaDataValue("slicer:root:", e->getMetaData()); const Slice::TypePtr t = e; -- cgit v1.2.3