Template Class StateMachine

Class Documentation

template<typename State, typename Trigger>
class StateMachine

Requires: std::copy_constructible<State> && std::copy_constructible<Trigger> && std::equality_comparable<State> && std::equality_comparable<Trigger>

A transition table for one typed state domain.

Rules are tested in insertion order; the first matching rule whose guard succeeds wins. Guards and actions may inspect other machines, allowing a game to compose state domains without requiring a controller or machine hierarchy. The machine is owned by its caller and is not synchronized or reentrant during trigger(). Stored callbacks own their captures; borrowed targets must survive use/removal. state() borrows this machine. Guards may add rules for later consideration in the same trigger; hooks for a chosen transition are copied before calling exit. Order is exit -> state assignment -> action -> enter. Exceptions propagate and stop that sequence: exit failure keeps old state, action/enter failure keeps new state; throwing State assignment follows that type’s guarantee. No rollback.

See also

State utilities

Template Parameters:
  • State – Copyable equality-comparable state identity; transitions assign it.

  • Trigger – Copyable equality-comparable event identity, distinct from State’s domain.

Public Types

using Guard = std::function<bool()>

Owned synchronous predicate; an empty guard always permits its matching rule.

using Action = std::function<void()>

Owned synchronous transition/entry/exit callback; empty means no callback.

Public Functions

inline explicit StateMachine(State initial)

Creates an empty rule/hook table at the supplied state.

Parameters:

initial – Initial owned state, moved into the machine. No entry hook runs. State construction failures propagate. The caller controls the machine’s lifetime/thread.

inline void add_transition(State from, Trigger trigger, State to, Guard guard = {}, Action action = {})

Appends one rule; earlier matching rules retain priority.

Parameters:
  • from – State from which this rule is eligible.

  • trigger – Trigger value compared for equality at dispatch.

  • to – State to install if this rule is selected.

  • guard – Optional owned predicate, invoked only for matching from/trigger; empty means true.

  • action – Optional owned callback after state assignment and before the entry hook. Copies/moves and allocation can throw. Captured borrowed targets outlive invocation. A guard may append rules considered later in the same trigger; do not reenter trigger().

inline void on_enter(State state, Action action)

Registers or replaces the entry hook for a state.

Parameters:
  • state – State identity to match, copied/moved into the hook table.

  • action – Owned synchronous hook; empty disables that state’s hook. Registration does not invoke the hook. Replacement and allocation follow the value/callable guarantees; borrowed captures must survive future use/removal.

inline void on_exit(State state, Action action)

Registers or replaces the exit hook for a state.

Parameters:
  • state – State identity to match, copied/moved into the hook table.

  • action – Owned synchronous hook; empty disables that state’s hook. Registration does not invoke the hook. Replacement and allocation follow the value/callable guarantees; borrowed captures must survive future use/removal.

inline const State &state() const

Declaration: [[nodiscard]]

Borrows the current state stored by this machine.

Returns:

Reference valid while the machine lives; later transitions assign this same storage. Copy the value to retain an independent sample. Access must not race mutation.

inline bool trigger(const Trigger &event)

Executes the first matching rule whose guard permits it.

Parameters:

event – Borrowed trigger identity, inspected synchronously.

Returns:

True when a rule was executed, including self-transitions; false for no eligible rule. The sequence is exit hook, state assignment, action, then entry hook. Hooks for the chosen transition are copied before exit runs. Exceptions propagate without rollback: exit failure retains the old state; action/entry failure retains the new state. A throwing State assignment has its own partial-effect guarantee. No synchronization or recursive trigger support is provided; hook changes affect later selections.