summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2020-10-17 12:06:12 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2020-10-17 12:06:12 +0100
commit9e7807baa8d9fffe593f6d7b9ef394ccb7a06765 (patch)
treee8b7f3917b6cdf8bb01091ee589642dcdc538acd
parentSupport model parts that are abstract classes with functions (diff)
downloadslicer-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.h66
-rw-r--r--slicer/slicer/modelPartsTypes.h4
-rw-r--r--slicer/slicer/modelPartsTypes.impl.h33
-rw-r--r--slicer/tool/parser.cpp20
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;