diff --git a/auto.hh b/auto.hh index 2b01fcd..16f6e9e 100644 --- a/auto.hh +++ b/auto.hh @@ -11,13 +11,22 @@ #include "type_utils.hxx" +template +struct NoopAutoLogger { + template class NewState, + template class OldState> + void log() { + } +}; + template class PInterface, class AllowedTransitions, - template class ...States> + class States, + template class Logger = NoopAutoLogger> class Auto { - using self_t = Auto; + using self_t = Auto; using intf_t = PInterface; - using ttlist = TTList; + using ttlist = States; template class State> struct Automaker { @@ -53,6 +62,8 @@ class Auto { StateData data_[2]; bool data_pos_; + Logger logger; + StateData &cur_data() { return data_[data_pos_]; } @@ -63,6 +74,9 @@ class Auto { Auto() : data_pos_(0) {} + Auto(Logger &&log) + : data_pos_(0), logger(log) {} + public: auto &get_state() { return *cur_data().template get_data(); @@ -80,6 +94,14 @@ public: return res; } + template class InitialState, class ...Args> + static Auto init(Logger &&logger, Args&& ...args) { + auto res = Auto{std::move(logger)}; + res.cur_data().template enter( + std::forward(args)...); + return res; + } + template class NewState, class ...Args> void enter(Args&& ...args) { other_data().template enter( @@ -88,14 +110,6 @@ public: data_pos_ = !data_pos_; } - template class NewState, - template class OldState, - class Auto> - static void default_logger(Auto) { - std::clog << "transition from " << typeid(OldState).name() << " to " - << typeid(NewState).name() << std::endl; - } - template class NewState, template class OldState, class ...Args> @@ -108,13 +122,7 @@ public: /* traits on variadic templates would be mandatory, which is too annoying to be worth it */ -#ifdef DEFAULT_LOG_TRANSITIONS -# define LOG_TRANSITIONS default_logger -#endif - -#ifdef LOG_TRANSITIONS - LOG_TRANSITIONS(this); -#endif + logger.template log(); enter(std::forward(args)...); } diff --git a/test.cc b/test.cc index 24eb3cd..24aa85b 100644 --- a/test.cc +++ b/test.cc @@ -44,11 +44,41 @@ struct StateB : ExInterface { }; -using trans = TList>; -using MyAuto = Auto; +template +struct OverkillLogger { + size_t log_count = 0; -int main() { + OverkillLogger(size_t msg_id) + : log_count{msg_id} {} + + template class NewState, + template class OldState> + void log() { + std::clog << log_count++ << " transition from " + << typeid(OldState).name() << " to " + << typeid(NewState).name() << std::endl; + } +}; + +using Transitions = TList>; +using States = TTList; +using MyAuto = Auto; +using MyLoggingAuto = Auto; + +void logging_example() { + auto logger = OverkillLogger{42}; + auto a = MyLoggingAuto::template init(std::move(logger), 1); + a.get_state().callback(a); + a.get_state().callback(a); +} + +void silent_example() { auto a = MyAuto::template init(1); a.get_state().callback(a); a.get_state().callback(a); } + +int main() { + logging_example(); + silent_example(); +}