1 #pragma once 2 3 #include <bitset> 4 5 enum class ReportFlags 6 { 7 enabled, 8 valid 9 }; 10 11 enum class StateEvent 12 { 13 active, 14 inactive, 15 activated, 16 deactivated 17 }; 18 19 template <class T> 20 concept boolean = std::is_same_v<T, bool>; 21 22 template <class Flags, class Object, Flags... Keys> 23 class State 24 { 25 public: State(Object & object)26 explicit State(Object& object) : object(object) {} 27 28 template <Flags... Indexes> set(boolean auto...values)29 StateEvent set(boolean auto... values) 30 { 31 static_assert(sizeof...(Indexes) == sizeof...(values)); 32 33 const bool previous = flags.all(); 34 35 (flags.set(indexOf<0, Indexes, Keys...>(), values), ...); 36 37 if (previous != flags.all()) 38 { 39 if (flags.all()) 40 { 41 object.activate(); 42 return StateEvent::activated; 43 } 44 else 45 { 46 object.deactivate(); 47 return StateEvent::deactivated; 48 } 49 } 50 51 return flags.all() ? StateEvent::active : StateEvent::inactive; 52 } 53 54 template <Flags Index> get() const55 bool get() const 56 { 57 return flags.test(indexOf<0, Index, Keys...>()); 58 } 59 isActive() const60 bool isActive() const 61 { 62 return flags.all(); 63 } 64 65 private: 66 template <size_t Index, Flags flag, Flags it, Flags... list> indexOf()67 static constexpr size_t indexOf() 68 { 69 if constexpr (flag == it) 70 { 71 return Index; 72 } 73 else 74 { 75 return indexOf<Index + 1, flag, list...>(); 76 } 77 } 78 79 Object& object; 80 std::bitset<sizeof...(Keys)> flags{0}; 81 }; 82