#pragma once #include #include #include /// A type (to specialize) that provides a count for an enum. /// Example: /// template<> struct enum_info_t /// { static constexpr auto count = MyEnum::COUNT; }; template struct enum_info_t {}; /// \return the count of an enum. template constexpr size_t enum_count() { return static_cast(enum_info_t::count); } /// A bit set indexed by an enum type. template class enum_set_t : private std::bitset()> { private: using super = std::bitset()>; static size_t index_of(T t) { return static_cast(t); } explicit enum_set_t(unsigned long raw) : super(raw) {} public: enum_set_t() = default; /*implicit*/ enum_set_t(T v) { set(v); } static enum_set_t from_raw(unsigned long v) { return enum_set_t{v}; } unsigned long to_raw() const { return super::to_ulong(); } bool get(T t) const { return super::test(index_of(t)); } void set(T t, bool v = true) { super::set(index_of(t), v); } void clear(T t) { super::reset(index_of(t)); } bool none() const { return super::none(); } bool any() const { return super::any(); } bool operator==(const enum_set_t &rhs) const { return super::operator==(rhs); } bool operator!=(const enum_set_t &rhs) const { return super::operator!=(rhs); } }; /// An array of Elem indexed by an enum class. template class enum_array_t : public std::array()> { using super = std::array()>; using base_type_t = typename std::underlying_type::type; static int index_of(T t) { return static_cast(t); } public: Elem &at(T t) { return super::at(index_of(t)); } const Elem &at(T t) const { return super::at(index_of(t)); } Elem &operator[](T t) { return super::operator[](index_of(t)); } const Elem &operator[](T t) const { return super::operator[](index_of(t)); } }; /// A counting iterator for an enum class. /// This enumerates the values of an enum class from 0 up to (not including) count. /// Example: /// for (auto v : enum_iter_t) {...} template class enum_iter_t { using base_type_t = typename std::underlying_type::type; struct iterator_t { friend class enum_iter_t; using iterator_category = std::forward_iterator_tag; using value_type = T; using difference_type = long; explicit iterator_t(base_type_t v) : v_(v) {} T operator*() const { return static_cast(v_); } const T *operator->() const { return static_cast(v_); } iterator_t &operator++() { v_ += 1; return *this; } iterator_t operator++(int) { auto res = *this; v_ += 1; return res; } bool operator==(iterator_t rhs) const { return v_ == rhs.v_; } bool operator!=(iterator_t rhs) const { return v_ != rhs.v_; } private: base_type_t v_{}; }; public: iterator_t begin() const { return iterator_t{0}; } iterator_t end() const { return iterator_t{static_cast(enum_count())}; } };