| #pragma once |
| |
| #include <bitset> |
| |
| enum class ReportFlags |
| { |
| enabled, |
| valid |
| }; |
| |
| enum class StateEvent |
| { |
| active, |
| inactive, |
| activated, |
| deactivated |
| }; |
| |
| template <class T> |
| concept boolean = std::is_same_v<T, bool>; |
| |
| template <class Flags, class Object, Flags... Keys> |
| class State |
| { |
| public: |
| explicit State(Object& object) : object(object) |
| {} |
| |
| template <Flags... Indexes> |
| StateEvent set(boolean auto... values) |
| { |
| static_assert(sizeof...(Indexes) == sizeof...(values)); |
| |
| const bool previous = flags.all(); |
| |
| (flags.set(indexOf<0, Indexes, Keys...>(), values), ...); |
| |
| if (previous != flags.all()) |
| { |
| if (flags.all()) |
| { |
| object.activate(); |
| return StateEvent::activated; |
| } |
| else |
| { |
| object.deactivate(); |
| return StateEvent::deactivated; |
| } |
| } |
| |
| return flags.all() ? StateEvent::active : StateEvent::inactive; |
| } |
| |
| template <Flags Index> |
| bool get() const |
| { |
| return flags.test(indexOf<0, Index, Keys...>()); |
| } |
| |
| bool isActive() const |
| { |
| return flags.all(); |
| } |
| |
| private: |
| template <size_t Index, Flags flag, Flags it, Flags... list> |
| static constexpr size_t indexOf() |
| { |
| if constexpr (flag == it) |
| { |
| return Index; |
| } |
| else |
| { |
| return indexOf<Index + 1, flag, list...>(); |
| } |
| } |
| |
| Object& object; |
| std::bitset<sizeof...(Keys)> flags{0}; |
| }; |