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: 26 explicit State(Object& object) : object(object) 27 {} 28 29 template <Flags... Indexes> 30 StateEvent set(boolean auto... values) 31 { 32 static_assert(sizeof...(Indexes) == sizeof...(values)); 33 34 const bool previous = flags.all(); 35 36 (flags.set(indexOf<0, Indexes, Keys...>(), values), ...); 37 38 if (previous != flags.all()) 39 { 40 if (flags.all()) 41 { 42 object.activate(); 43 return StateEvent::activated; 44 } 45 else 46 { 47 object.deactivate(); 48 return StateEvent::deactivated; 49 } 50 } 51 52 return flags.all() ? StateEvent::active : StateEvent::inactive; 53 } 54 55 template <Flags Index> 56 bool get() const 57 { 58 return flags.test(indexOf<0, Index, Keys...>()); 59 } 60 61 bool isActive() const 62 { 63 return flags.all(); 64 } 65 66 private: 67 template <size_t Index, Flags flag, Flags it, Flags... list> 68 static constexpr size_t indexOf() 69 { 70 if constexpr (flag == it) 71 { 72 return Index; 73 } 74 else 75 { 76 return indexOf<Index + 1, flag, list...>(); 77 } 78 } 79 80 Object& object; 81 std::bitset<sizeof...(Keys)> flags{0}; 82 }; 83