diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2020-10-17 12:06:12 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2020-10-17 12:06:12 +0100 |
commit | 9e7807baa8d9fffe593f6d7b9ef394ccb7a06765 (patch) | |
tree | e8b7f3917b6cdf8bb01091ee589642dcdc538acd | |
parent | Support model parts that are abstract classes with functions (diff) | |
download | slicer-9e7807baa8d9fffe593f6d7b9ef394ccb7a06765.tar.bz2 slicer-9e7807baa8d9fffe593f6d7b9ef394ccb7a06765.tar.xz slicer-9e7807baa8d9fffe593f6d7b9ef394ccb7a06765.zip |
Custom enummap type
Starts down the constexpr route, removes some need for boost::multi_index
-rw-r--r-- | slicer/slicer/enumMap.h | 66 | ||||
-rw-r--r-- | slicer/slicer/modelPartsTypes.h | 4 | ||||
-rw-r--r-- | slicer/slicer/modelPartsTypes.impl.h | 33 | ||||
-rw-r--r-- | slicer/tool/parser.cpp | 20 |
4 files changed, 91 insertions, 32 deletions
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<typename E> class EnumMap { + public: + struct Node { + E value; + std::string_view name; + const std::string * nameStr; + }; + + template<EnumMapKey Key, typename T> + 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<typename E, std::size_t N> class EnumMapImpl : public EnumMap<E> { + public: + using NodeType = typename EnumMap<E>::Node; + template<std::size_t n> using Arr = std::array<NodeType, n>; + + constexpr const NodeType * + begin() const override + { + return arr.begin(); + } + + constexpr const NodeType * + end() const override + { + return arr.end(); + } + + inline constexpr EnumMapImpl(Arr<N> a) : arr(std::move(a)) { } + const Arr<N> 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<typename T> class EnumMap; template<typename T> class DLL_PUBLIC ModelPartForEnum : public ModelPartForEnumBase, protected ModelPartModel<T> { 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<T> & 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 <Ice/StreamHelpers.h> #include <IceUtil/Optional.h> @@ -659,18 +660,6 @@ namespace Slicer { } // ModelPartForEnum - template<typename T> using EnumPair = std::pair<T, std::string>; - - template<typename T> - class ModelPartForEnum<T>::Enumerations : - public boost::multi_index_container<EnumPair<T>, - boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::member< - EnumPair<T>, const T, &EnumPair<T>::first>>, - boost::multi_index::ordered_unique< - boost::multi_index::member<EnumPair<T>, const std::string, &EnumPair<T>::second>, - std::less<>>>> { - }; - template<typename T> ModelPartForEnum<T>::ModelPartForEnum(T * s) : ModelPartModel<T>(s) { } template<typename T> @@ -680,14 +669,12 @@ namespace Slicer { return metadata; } - template<int Side, typename Ex, typename ExP, typename T, typename V, typename R> - inline const auto & - ModelPartForEnumLookup( - const typename ModelPartForEnum<T>::Enumerations & enumerations, const V & val, R EnumPair<T>::*rv) + template<EnumMapKey Key, typename Ex, typename ExP, typename T, typename V> + inline const auto * + ModelPartForEnumLookup(const EnumMap<T> & enumerations, const V & val) { - const auto & side = enumerations.template get<Side>(); - if (auto i = side.find(val); i != side.end()) { - return (*i).*rv; + if (auto i = enumerations.template find<Key>(val)) { + return i; } throw Ex(ExP(val), typeid(T).name()); } @@ -696,16 +683,16 @@ namespace Slicer { T ModelPartForEnum<T>::lookup(const std::string_view & val) { - return ModelPartForEnumLookup<1, InvalidEnumerationSymbol, std::string, T>( - enumerations, val, &EnumPair<T>::first); + return ModelPartForEnumLookup<EnumMapKey::Name, InvalidEnumerationSymbol, std::string, T>(enumerations(), val) + ->value; } template<typename T> const std::string & ModelPartForEnum<T>::lookup(T val) { - return ModelPartForEnumLookup<0, InvalidEnumerationValue, ::Ice::Int, T>( - enumerations, val, &EnumPair<T>::second); + return *ModelPartForEnumLookup<EnumMapKey::Value, InvalidEnumerationValue, ::Ice::Int, T>(enumerations(), val) + ->nameStr; } template<typename T> 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; |