1973b4bb0SKrzysztof Grobelny #pragma once 2973b4bb0SKrzysztof Grobelny 3973b4bb0SKrzysztof Grobelny #include <bitset> 4973b4bb0SKrzysztof Grobelny 5973b4bb0SKrzysztof Grobelny enum class ReportFlags 6973b4bb0SKrzysztof Grobelny { 7973b4bb0SKrzysztof Grobelny enabled, 8973b4bb0SKrzysztof Grobelny valid 9973b4bb0SKrzysztof Grobelny }; 10973b4bb0SKrzysztof Grobelny 11973b4bb0SKrzysztof Grobelny enum class StateEvent 12973b4bb0SKrzysztof Grobelny { 13973b4bb0SKrzysztof Grobelny active, 14973b4bb0SKrzysztof Grobelny inactive, 15973b4bb0SKrzysztof Grobelny activated, 16973b4bb0SKrzysztof Grobelny deactivated 17973b4bb0SKrzysztof Grobelny }; 18973b4bb0SKrzysztof Grobelny 19973b4bb0SKrzysztof Grobelny template <class T> 20973b4bb0SKrzysztof Grobelny concept boolean = std::is_same_v<T, bool>; 21973b4bb0SKrzysztof Grobelny 22973b4bb0SKrzysztof Grobelny template <class Flags, class Object, Flags... Keys> 23973b4bb0SKrzysztof Grobelny class State 24973b4bb0SKrzysztof Grobelny { 25973b4bb0SKrzysztof Grobelny public: State(Object & object)26*3a1c297aSPatrick Williams explicit State(Object& object) : object(object) {} 27973b4bb0SKrzysztof Grobelny 28973b4bb0SKrzysztof Grobelny template <Flags... Indexes> set(boolean auto...values)29973b4bb0SKrzysztof Grobelny StateEvent set(boolean auto... values) 30973b4bb0SKrzysztof Grobelny { 31973b4bb0SKrzysztof Grobelny static_assert(sizeof...(Indexes) == sizeof...(values)); 32973b4bb0SKrzysztof Grobelny 33973b4bb0SKrzysztof Grobelny const bool previous = flags.all(); 34973b4bb0SKrzysztof Grobelny 35973b4bb0SKrzysztof Grobelny (flags.set(indexOf<0, Indexes, Keys...>(), values), ...); 36973b4bb0SKrzysztof Grobelny 37973b4bb0SKrzysztof Grobelny if (previous != flags.all()) 38973b4bb0SKrzysztof Grobelny { 39973b4bb0SKrzysztof Grobelny if (flags.all()) 40973b4bb0SKrzysztof Grobelny { 41973b4bb0SKrzysztof Grobelny object.activate(); 42973b4bb0SKrzysztof Grobelny return StateEvent::activated; 43973b4bb0SKrzysztof Grobelny } 44973b4bb0SKrzysztof Grobelny else 45973b4bb0SKrzysztof Grobelny { 46973b4bb0SKrzysztof Grobelny object.deactivate(); 47973b4bb0SKrzysztof Grobelny return StateEvent::deactivated; 48973b4bb0SKrzysztof Grobelny } 49973b4bb0SKrzysztof Grobelny } 50973b4bb0SKrzysztof Grobelny 51973b4bb0SKrzysztof Grobelny return flags.all() ? StateEvent::active : StateEvent::inactive; 52973b4bb0SKrzysztof Grobelny } 53973b4bb0SKrzysztof Grobelny 54973b4bb0SKrzysztof Grobelny template <Flags Index> get() const55973b4bb0SKrzysztof Grobelny bool get() const 56973b4bb0SKrzysztof Grobelny { 57973b4bb0SKrzysztof Grobelny return flags.test(indexOf<0, Index, Keys...>()); 58973b4bb0SKrzysztof Grobelny } 59973b4bb0SKrzysztof Grobelny isActive() const60973b4bb0SKrzysztof Grobelny bool isActive() const 61973b4bb0SKrzysztof Grobelny { 62973b4bb0SKrzysztof Grobelny return flags.all(); 63973b4bb0SKrzysztof Grobelny } 64973b4bb0SKrzysztof Grobelny 65973b4bb0SKrzysztof Grobelny private: 66973b4bb0SKrzysztof Grobelny template <size_t Index, Flags flag, Flags it, Flags... list> indexOf()67973b4bb0SKrzysztof Grobelny static constexpr size_t indexOf() 68973b4bb0SKrzysztof Grobelny { 69973b4bb0SKrzysztof Grobelny if constexpr (flag == it) 70973b4bb0SKrzysztof Grobelny { 71973b4bb0SKrzysztof Grobelny return Index; 72973b4bb0SKrzysztof Grobelny } 73973b4bb0SKrzysztof Grobelny else 74973b4bb0SKrzysztof Grobelny { 75973b4bb0SKrzysztof Grobelny return indexOf<Index + 1, flag, list...>(); 76973b4bb0SKrzysztof Grobelny } 77973b4bb0SKrzysztof Grobelny } 78973b4bb0SKrzysztof Grobelny 79973b4bb0SKrzysztof Grobelny Object& object; 80973b4bb0SKrzysztof Grobelny std::bitset<sizeof...(Keys)> flags{0}; 81973b4bb0SKrzysztof Grobelny }; 82