tkem / fsmlite

Lightweight finite state machine framework for C++11
MIT License
156 stars 25 forks source link

Doc or example of mapping a simple type to event type #24

Closed kuuse closed 4 years ago

kuuse commented 4 years ago

Hi,

Is there a way to "map" an event defined as an empty struct to a simple type such as int? I cannot find any example or anything in the docs which describes what I want to achieve, so I explain with a couple of examples:

Using a switch works, but makes the code redundant, as any added event to the player class (declaration and transition_table antry) would also require an switch state:

enum event_index {OPEN_CLOSE, CD_DETECTED, PLAY, PAUSE, STOP};

// Straight-forward, but a bit "clumsy"
void test_player_switch(enum event_index e)
{
  player p;
  switch (e)
  {
  case OPEN_CLOSE:
    p.process_event(player::open_close());
    break;
  case CD_DETECTED:
    p.process_event(player::open_close());
    break;
  case PLAY:
    p.process_event(player::cd_detected{"louie, louie"});
    break;
  case PAUSE:
    p.process_event(player::play());
    break;
  case STOP:
    p.process_event(player::pause());
    break;
  default:
    break
  }
}

Instead of using a switch, I would like "map" an integer to en event, like this: (note this is pseudo-code, and I am not sure it is even possible to do it that way):

// Map Event Index to their corresponding Event
const std::unordered_map<enum event_index, ??? EventType<T> ???> EventMap = {
  {OPEN_CLOSE  , player::open_close()},
  {CD_DETECTED , player::cd_detected()},
  {PLAY        , player::play()},
  {PAUSE       , player::pause()},
  {STOP        , player::stop()},
};

void test_player_map(enum event_index e)
{
  player p;
  auto ??? event ??? = EventMap.find(e);
  p.process_event(event); // How to get type-of-event ???
}

Or, if there is an undocumented way of doing this in another way, I would appreciate knowing about that.

BR, Johan

kuuse commented 4 years ago

Not exactly an answer to my own question, but more an example how to use Guards to resolve the "mapping" problem between an integer an event. Note thay the example does not use Tag Dispatching (empty structs) as event type, though.

The attach source code validates a set of PIN code, using both Guards and Actions (both with and without the 'event' argument). I think only 'test_recursive.cpp' uses an Action with argument in a similar fashion. I found it by coincidence. Tip: Mention Argument(event) and Guards in the documentation.

There are better ways to validate a PIN code, but I think this may be a useful example for usage of 'fsmlite'.

Feel free to do as you please with the source code.

test_pin_code.cpp.zip

tkem commented 4 years ago

Thanks for your interest, but using distinct types as events is one of the basic concepts of this library. If you want to use enums without any extra data as input, there are probably other state machine implementations better suited to your needs.