From ee72566650d17b53b49774942230a4dc12e77dd6 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Wed, 14 Jun 2017 19:47:08 -0700 Subject: [PATCH] finished implementing util::Enum_set --- src/util/enum.h | 237 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 234 insertions(+), 3 deletions(-) diff --git a/src/util/enum.h b/src/util/enum.h index 09a923f..13f96af 100644 --- a/src/util/enum.h +++ b/src/util/enum.h @@ -26,6 +26,7 @@ #include #include +#include #include "constexpr_array.h" #include "bitset.h" @@ -193,17 +194,247 @@ static constexpr Enum_values Default_enum_traits enum_traits_resolve_function(Enum); } +/** behaves like a std::set */ template class Enum_set { private: - util::bitset::value_count> bits; + typedef util::bitset::value_count> Bits; public: - constexpr enum_set() noexcept : bits(0) + typedef T key_type; + typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T &reference; + typedef const T &const_reference; + typedef T *pointer; + typedef const T *const_pointer; + class iterator { + template + friend class Enum_set; + + public: + typedef std::ptrdiff_t difference_type; + typedef T value_type; + typedef const T *pointer; + typedef const T &reference; + std::bidirectional_iterator_tag iterator_category; + + private: + const Enum_set *enum_set; + std::size_t index; + + public: + constexpr iterator() noexcept : enum_set(nullptr), index(0) + { + } + + private: + constexpr iterator(const Enum_set *enum_set, std::size_t index) noexcept + : enum_set(enum_set), + index(index) + { + } + static constexpr iterator first_at_or_after(const Enum_set *enum_set, + std::size_t index) noexcept + { + return iterator(enum_set, enum_set->bits.find_first(true, index)); + } + static constexpr iterator first_at_or_before(const Enum_set *enum_set, + std::size_t index) noexcept + { + return iterator(enum_set, enum_set->bits.find_last(true, index)); + } + + public: + constexpr bool operator==(const iterator &rt) const noexcept + { + return index == rt.index && enum_set == rt.enum_set; + } + constexpr bool operator!=(const iterator &rt) const noexcept + { + return !operator==(rt); + } + constexpr iterator &operator++() noexcept + { + *this = first_at_or_after(enum_set, index + 1); + return *this; + } + constexpr iterator &operator--() noexcept + { + *this = first_at_or_before(enum_set, index - 1); + return *this; + } + constexpr iterator operator++(int) noexcept + { + auto retval = *this; + operator++(); + return retval; + } + constexpr iterator operator--(int) noexcept + { + auto retval = *this; + operator--(); + return retval; + } + constexpr const T &operator*() const noexcept + { + return Enum_traits::values[index]; + } + constexpr const T *operator->() const noexcept + { + return &operator*(); + } + }; + typedef iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef reverse_iterator reverse_const_iterator; + +private: + Bits bits; + +public: + constexpr Enum_set() noexcept : bits(0) + { + } + template + constexpr Enum_set(Iter first, Iter last) + : Enum_set() + { + insert(std::move(first), std::move(last)); + } + constexpr Enum_set(std::initializer_list il) noexcept : Enum_set(il.begin(), il.end()) + { + } + constexpr Enum_set &operator=(std::initializer_list il) noexcept + { + *this = Enum_set(il); + return *this; + } + constexpr iterator begin() const noexcept + { + return iterator::first_at_or_after(this, 0); + } + constexpr iterator end() const noexcept + { + return iterator(this, Bits::npos); + } + constexpr iterator cbegin() const noexcept + { + return begin(); + } + constexpr iterator cend() const noexcept + { + return end(); + } + constexpr bool empty() const noexcept + { + return bits.none(); + } + constexpr std::size_t size() const noexcept + { + return bits.count(); + } + constexpr std::size_t max_size() const noexcept + { + return bits.size(); + } + constexpr void clear() noexcept + { + bits = Bits(); + } + constexpr std::pair insert(T value) noexcept + { + std::size_t index = Enum_traits::find_value(value); + bool inserted = !bits[index]; + bits[index] = true; + return {iterator(this, index), inserted}; + } + constexpr iterator insert(iterator hint, T value) noexcept + { + std::size_t index = Enum_traits::find_value(value); + bits[index] = true; + return iterator(this, index); + } + template + constexpr void insert(Iter first, Iter last) + { + for(; first != last; ++first) + insert(*first); + } + constexpr void insert(std::initializer_list il) noexcept + { + insert(il.begin(), il.end()); + } + template + std::pair emplace(Args &&... args) + { + return insert(T(std::forward(args)...)); + } + template + iterator emplace_hint(iterator hint, Args &&... args) + { + return insert(hint, T(std::forward(args)...)); + } + constexpr std::size_t erase(T value) noexcept + { + std::size_t index = Enum_traits::find_value(value); + std::size_t retval = 0; + if(index < bits.size()) + { + retval = bits[index] ? 1 : 0; + bits[index] = false; + } + return retval; + } + constexpr iterator erase(iterator pos) noexcept + { + auto retval = pos; + ++retval; + bits[pos.index] = false; + return retval; + } + constexpr iterator erase(iterator first, iterator last) noexcept + { + while(first != last) + first = erase(first); + return first; + } + /** invalidates all iterators, all references still valid because they are bound to static + * objects */ + constexpr void swap(Enum_set &other) noexcept + { + using std::swap; + swap(bits, other.bits); + } + constexpr std::size_t count(T value) const noexcept + { + std::size_t index = Enum_traits::find_value(value); + if(index < bits.size() && bits[index]) + return 1; + return 0; + } + constexpr iterator find(T value) const noexcept + { + std::size_t index = Enum_traits::find_value(value); + if(index < bits.size() && bits[index]) + return iterator(this, index); + return 0; + } + std::pair equal_range(T value) const noexcept + { + std::size_t index = Enum_traits::find_value(value); + if(index < bits.size() && bits[index]) + { + auto first = iterator(this, index); + auto last = first; + ++last; + return {first, last}; + } + return {end(), end()}; } -#warning finish }; } } -- 2.30.2