summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2020-10-18 18:11:27 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2020-10-18 18:11:27 +0100
commit2b0e3626deb33f95aeda00807278bad8c9e02b1f (patch)
treede0cc7a36d59f30dfcc0049e637ec818bab451e2
parentRemove unrequired case_less comparator (diff)
downloadslicer-2b0e3626deb33f95aeda00807278bad8c9e02b1f.tar.bz2
slicer-2b0e3626deb33f95aeda00807278bad8c9e02b1f.tar.xz
slicer-2b0e3626deb33f95aeda00807278bad8c9e02b1f.zip
No virtuals in enum and hook maps
Allows static_assert tests.
-rw-r--r--slicer/slicer/Jamfile.jam6
-rw-r--r--slicer/slicer/enum-test.cpp22
-rw-r--r--slicer/slicer/enumMap.h31
-rw-r--r--slicer/slicer/hook-test.cpp55
-rw-r--r--slicer/slicer/hookMap.h97
-rw-r--r--slicer/slicer/modelPartsTypes.impl.h7
6 files changed, 172 insertions, 46 deletions
diff --git a/slicer/slicer/Jamfile.jam b/slicer/slicer/Jamfile.jam
index f1ba4b1..38a0c66 100644
--- a/slicer/slicer/Jamfile.jam
+++ b/slicer/slicer/Jamfile.jam
@@ -2,9 +2,13 @@ import package ;
lib stdc++fs ;
+obj enum-test : enum-test.cpp ;
+obj hook-test : hook-test.cpp : <use>..//adhocutil <implicit-dependency>common ;
+
obj common : common.ice : <toolset>tidy:<checker>none ;
+
lib slicer :
- [ glob *.cpp ]
+ [ glob *.cpp : *-test.cpp ]
common
:
<library>..//Ice
diff --git a/slicer/slicer/enum-test.cpp b/slicer/slicer/enum-test.cpp
new file mode 100644
index 0000000..166804f
--- /dev/null
+++ b/slicer/slicer/enum-test.cpp
@@ -0,0 +1,22 @@
+#include "enumMap.h"
+
+enum class Es { one, two, three };
+const std::string one {"one"}, two {"two"}, three {"three"};
+
+constexpr Slicer::EnumMapImpl<Es, 3> em {{{
+ {Es::one, "one", &one},
+ {Es::two, "two", &two},
+ {Es::three, "three", &three},
+}}};
+
+static_assert(em.arr.size() == 3);
+static_assert(em.arr[0].value == Es::one);
+static_assert(em.arr[1].name == "two");
+static_assert(em.arr[1].nameStr == &two);
+static_assert(em.arr[2].value == Es::three);
+
+static_assert(em.find<Slicer::EnumMapKey::Name>("one")->value == Es::one);
+static_assert(em.find<Slicer::EnumMapKey::Name>("three")->value == Es::three);
+static_assert(em.find<Slicer::EnumMapKey::Value>(Es::one)->name == "one");
+static_assert(em.find<Slicer::EnumMapKey::Value>(Es::three)->name == "three");
+static_assert(!em.find<Slicer::EnumMapKey::Name>("four"));
diff --git a/slicer/slicer/enumMap.h b/slicer/slicer/enumMap.h
index 98ecd04..a7b42c2 100644
--- a/slicer/slicer/enumMap.h
+++ b/slicer/slicer/enumMap.h
@@ -1,6 +1,10 @@
#ifndef SLICER_ENUM_MAP_H
#define SLICER_ENUM_MAP_H
+#include <array>
+#include <string>
+#include <string_view>
+
namespace Slicer {
enum class EnumMapKey {
Value,
@@ -16,12 +20,10 @@ namespace Slicer {
};
template<EnumMapKey Key, typename T>
- constexpr inline const Node *
- find(const T & v) const
+ [[nodiscard]] constexpr inline const Node *
+ find(const T & v) const noexcept
{
- auto b = begin();
- const auto e = end();
- while (b != e) {
+ for (auto b = begin; b != end; b++) {
if constexpr (Key == EnumMapKey::Value) {
if (b->value == v) {
return b;
@@ -32,13 +34,12 @@ namespace Slicer {
return b;
}
}
- ++b;
}
return nullptr;
}
- virtual constexpr const Node * begin() const = 0;
- virtual constexpr const Node * end() const = 0;
+ const Node * begin {};
+ const Node * end {};
};
template<typename E, std::size_t N> class EnumMapImpl : public EnumMap<E> {
@@ -46,19 +47,11 @@ namespace Slicer {
using NodeType = typename EnumMap<E>::Node;
template<std::size_t n> using Arr = std::array<NodeType, n>;
- constexpr const NodeType *
- begin() const override
+ inline constexpr EnumMapImpl(Arr<N> a) : arr(std::move(a))
{
- return arr.begin();
+ EnumMap<E>::begin = arr.begin();
+ EnumMap<E>::end = arr.end();
}
-
- constexpr const NodeType *
- end() const override
- {
- return arr.end();
- }
-
- inline constexpr EnumMapImpl(Arr<N> a) : arr(std::move(a)) { }
const Arr<N> arr;
};
}
diff --git a/slicer/slicer/hook-test.cpp b/slicer/slicer/hook-test.cpp
new file mode 100644
index 0000000..11641c2
--- /dev/null
+++ b/slicer/slicer/hook-test.cpp
@@ -0,0 +1,55 @@
+#include "hookMap.h"
+#include "modelPartsTypes.impl.h"
+
+#include <string>
+
+struct S {
+ int aa;
+ int aA;
+ int Aa;
+ int AA;
+ std::string b;
+};
+const std::string aa {"aa"}, aA {"aA"}, Aa {"Aa"}, AA {"AA"}, b {"b"};
+
+using C = Slicer::ModelPartForComplex<S>;
+constexpr C::Hook<int, Slicer::ModelPartForSimple<int>> haa {&S::aa, "aa", "aa", &aa};
+constexpr C::Hook<int, Slicer::ModelPartForSimple<int>> haA {&S::aA, "aA", "aa", &aA};
+constexpr C::Hook<int, Slicer::ModelPartForSimple<int>> hAa {&S::Aa, "Aa", "aa", &Aa};
+constexpr C::Hook<int, Slicer::ModelPartForSimple<int>> hAA {&S::AA, "AA", "aa", &AA};
+constexpr C::Hook<std::string, Slicer::ModelPartForSimple<std::string>> hb {&S::b, "b", "b", &b};
+constexpr Slicer::HooksImpl<S, 5> h {{{&haa, &haA, &hAa, &hAA, &hb}}};
+
+static_assert(h.arr.size() == 5);
+static_assert(h.arr[0]->name == "aa");
+static_assert(h.arr[0]->nameLower == "aa");
+static_assert(h.arr[0]->nameStr == &aa);
+static_assert(h.arr[1]->name == "aA");
+static_assert(h.arr[1]->nameLower == "aa");
+static_assert(h.arr[1]->nameStr == &aA);
+static_assert(h.arr[4]->name == "b");
+static_assert(h.arr[4]->nameLower == "b");
+static_assert(h.arr[4]->nameStr == &b);
+
+constexpr auto aas = h.equal_range("aa");
+constexpr auto bbs = h.equal_range("bb");
+static_assert(aas.begin() != aas.end());
+static_assert(bbs.begin() == bbs.end());
+static_assert(aas.begin()->name == "aa");
+
+constexpr auto aa0 = aas.begin();
+static_assert(aa0->name == "aa");
+constexpr auto aa1 = aa0 + 1;
+static_assert(aa1 == aas.end());
+static_assert(std::distance(aas.begin(), aas.end()) == 1);
+static_assert(std::distance(bbs.begin(), bbs.end()) == 0);
+
+constexpr auto laas = h.equal_range_lower("aa");
+constexpr auto lAAs = h.equal_range_lower("AA");
+static_assert(std::distance(laas.begin(), laas.end()) == 4);
+static_assert(std::distance(lAAs.begin(), lAAs.end()) == 0);
+static_assert(laas.begin()->name == "aa");
+static_assert((laas.begin() + 1)->name == "aA");
+static_assert((laas.begin() + 2)->name == "Aa");
+static_assert((laas.begin() + 3)->name == "AA");
+static_assert((laas.begin() + 4) == laas.end());
diff --git a/slicer/slicer/hookMap.h b/slicer/slicer/hookMap.h
index fb75b33..5b99f96 100644
--- a/slicer/slicer/hookMap.h
+++ b/slicer/slicer/hookMap.h
@@ -15,43 +15,75 @@ namespace Slicer {
template<typename K> class iter : public std::iterator<std::bidirectional_iterator_tag, HookPtr> {
public:
- iter(const eq<K> * const r, const HookPtr * c) : range(r), cur(c)
+ constexpr inline iter(const eq<K> * const r, const HookPtr * c) : range(r), cur(c)
{
- operator++(); // move to first match
+ moveMatch();
}
- HookPtr
+ constexpr inline HookPtr
operator*() const
{
return *cur;
}
- void
+ constexpr inline HookPtr
+ operator->() const
+ {
+ return *cur;
+ }
+
+ constexpr inline void
operator++()
{
- for (; cur != range->e && (*cur)->*(range->name) != range->key; cur++) { }
+ if (cur++ != range->e) {
+ moveMatch();
+ }
}
- bool
+ constexpr inline iter
+ operator+(std::size_t n) const
+ {
+ auto i {*this};
+ while (n--) {
+ ++i;
+ }
+ return i;
+ }
+
+ constexpr inline bool
operator!=(const iter & other) const
{
return cur != other.cur;
}
+ constexpr inline bool
+ operator==(const iter & other) const
+ {
+ return cur == other.cur;
+ }
+
private:
+ constexpr void
+ moveMatch()
+ {
+ while (cur != range->e && (*cur)->*(range->name) != range->key) {
+ cur++;
+ }
+ }
+
const eq<K> * const range;
const HookPtr * cur;
};
template<typename K> class eq {
public:
- iter<K>
+ constexpr inline iter<K>
begin() const
{
return {this, b};
}
- iter<K>
+ constexpr inline iter<K>
end() const
{
return {this, e};
@@ -63,15 +95,39 @@ namespace Slicer {
};
template<typename K>
+ constexpr inline eq<K>
+ equal_range(K && k) const
+ {
+ return {std::move(k), &HookCommon::name, _begin, _end};
+ }
+
+ template<typename K>
+ constexpr inline eq<K>
+ equal_range_lower(K && k) const
+ {
+ return {std::move(k), &HookCommon::nameLower, _begin, _end};
+ }
+
+ template<typename K>
inline eq<K>
- equal_range(const K & k, bool matchCase) const
+ equal_range_nocase(const K & k) const
{
- return {matchCase ? k : boost::algorithm::to_lower_copy(k),
- matchCase ? &HookCommon::name : &HookCommon::nameLower, begin(), end()};
+ return equal_range_lower(boost::algorithm::to_lower_copy(k));
}
- virtual constexpr const HookPtr * begin() const = 0;
- virtual constexpr const HookPtr * end() const = 0;
+ constexpr inline auto
+ begin() const
+ {
+ return _begin;
+ }
+ constexpr inline auto
+ end() const
+ {
+ return _end;
+ }
+
+ const HookPtr * _begin {};
+ const HookPtr * _end {};
};
template<typename T, std::size_t N> class HooksImpl : public Hooks<T> {
@@ -79,21 +135,12 @@ namespace Slicer {
using HookPtr = typename Hooks<T>::HookPtr;
template<std::size_t n> using Arr = std::array<HookPtr, n>;
- inline constexpr HooksImpl(Arr<N> a) : arr(std::move(a)) { }
-
- constexpr const HookPtr *
- begin() const override
- {
- return arr.begin();
- }
-
- constexpr const HookPtr *
- end() const override
+ inline constexpr HooksImpl(Arr<N> a) : arr(std::move(a))
{
- return arr.end();
+ Hooks<T>::_begin = arr.begin();
+ Hooks<T>::_end = arr.end();
}
- private:
const Arr<N> arr;
};
}
diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h
index ebfd6d9..409a4ed 100644
--- a/slicer/slicer/modelPartsTypes.impl.h
+++ b/slicer/slicer/modelPartsTypes.impl.h
@@ -436,7 +436,12 @@ namespace Slicer {
ChildRef
ModelPartForComplex<T>::GetChildRef(const std::string & name, const HookFilter & flt, bool matchCase)
{
- return GetChildRefFromRange(hooks().equal_range(name, matchCase), flt);
+ if (matchCase) {
+ return GetChildRefFromRange(hooks().equal_range(name), flt);
+ }
+ else {
+ return GetChildRefFromRange(hooks().equal_range_nocase(name), flt);
+ }
}
template<typename T>