diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2020-10-18 18:11:27 +0100 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2020-10-18 18:11:27 +0100 | 
| commit | 2b0e3626deb33f95aeda00807278bad8c9e02b1f (patch) | |
| tree | de0cc7a36d59f30dfcc0049e637ec818bab451e2 | |
| parent | Remove unrequired case_less comparator (diff) | |
| download | slicer-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.jam | 6 | ||||
| -rw-r--r-- | slicer/slicer/enum-test.cpp | 22 | ||||
| -rw-r--r-- | slicer/slicer/enumMap.h | 31 | ||||
| -rw-r--r-- | slicer/slicer/hook-test.cpp | 55 | ||||
| -rw-r--r-- | slicer/slicer/hookMap.h | 97 | ||||
| -rw-r--r-- | slicer/slicer/modelPartsTypes.impl.h | 7 | 
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>  | 
