Skip to content

Commit

Permalink
Add fsm::row type (C++17 only).
Browse files Browse the repository at this point in the history
  • Loading branch information
tkem committed Feb 20, 2019
1 parent a4ff410 commit 19092ce
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 8 deletions.
35 changes: 33 additions & 2 deletions src/fsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ namespace fsmlite {
detail::invoke_as_binary_fn(action, self, event);
}

// clang++-50: constexpr function's return type 'void' is not a literal type
// clang++-5.0: constexpr function's return type 'void' is not a literal type
static /*constexpr*/ void process_event(std::nullptr_t, Derived& self, const Event& event) {
}

Expand Down Expand Up @@ -299,7 +299,6 @@ namespace fsmlite {
*
* @tparam guard a static `Guard` instance
*/

template<
State start,
class Event,
Expand Down Expand Up @@ -355,6 +354,38 @@ namespace fsmlite {
}
};

#if __cplusplus >= 201703L
/**
* Generic transition class template (requires C++17).
*
* @tparam start the start state of the transition
*
* @tparam Event the event type triggering the transition
*
* @tparam target the target state of the transition
*
* @tparam action a static action function pointer, or `nullptr`
*
* @tparam guard a static guard function pointer, or `nullptr`
*/
template<
State start,
class Event,
State target,
auto action = nullptr,
auto guard = nullptr
>
struct row : public row_base<start, Event, target> {
static void process_event(Derived& self, const Event& event) {
row_base<start, Event, target>::process_event(action, self, event);
}

static bool check_guard(const Derived& self, const Event& event) {
return row_base<start, Event, target>::check_guard(guard, self, event);
}
};
#endif

private:
template<class Event, class...> struct by_event_type;

Expand Down
1 change: 1 addition & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ check_PROGRAMS = \
test_mem_fn_row \
test_notrans \
test_recursive \
test_row \
test_scoped \
test_traits

Expand Down
7 changes: 1 addition & 6 deletions tests/test_basic_row.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
#include <cassert>
#include <functional>
#include <iostream>

#include "fsm.h"

using namespace std::placeholders;

int value = 0;

// global actions
Expand Down Expand Up @@ -48,12 +44,11 @@ class state_machine: public fsmlite::fsm<state_machine> {
basic_row< Running, event, Running, decltype(&m::store2), &m::store2, decltype(&m::is2), &m::is2 >,
basic_row< Running, event, Running, decltype(&m::store3), &m::store3, decltype(&m::is3), &m::is3 >,
basic_row< Running, event, Exit, decltype(&clear), &clear /* fallback */ >,
basic_row< Exit, event, Exit, decltype(nullptr), nullptr >
basic_row< Exit, event, Exit >
// ----------+--------+------+--------+---------------------+-----------+------------------+-------+-
>;
};


int main()
{
state_machine m;
Expand Down
88 changes: 88 additions & 0 deletions tests/test_row.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include <cassert>

#include "fsm.h"

#if __cplusplus >= 201703L

int value = 0;

// global actions

void store(int i) { value = i; }
void clear() { value = 0; }

// global guards

bool is1(int i) { return i == 1; }

// fsm

class state_machine: public fsmlite::fsm<state_machine> {
friend class fsm; // base class needs access to transition_table

public:
enum states { Init, Running, Exit };

using event = int;

public:

static void store2() { value = 2; }

static bool is2(int i) { return i == 2; }

void store3() { value = 3; }

bool is3(int i) const { return i == 3; }

private:
using m = state_machine;

using transition_table = table<
// Start Event Target Action Guard
// ----+--------+------+--------+-----------+-------+-
row< Init, event, Running, &store >,
row< Running, event, Running, &store, &is1 >,
row< Running, event, Running, &m::store2, &m::is2 >,
row< Running, event, Running, &m::store3, &m::is3 >,
row< Running, event, Exit, &clear >,
row< Exit, event, Exit >
// ----+--------+------+--------+-----------+-------+-
>;
};

#endif

int main()
{
#if __cplusplus >= 201703L
state_machine m;
assert(m.current_state() == state_machine::Init);
assert(value == 0);

m.process_event(42);
assert(m.current_state() == state_machine::Running);
assert(value == 42);

m.process_event(1);
assert(m.current_state() == state_machine::Running);
assert(value == 1);

m.process_event(2);
assert(m.current_state() == state_machine::Running);
assert(value == 2);

m.process_event(3);
assert(m.current_state() == state_machine::Running);
assert(value == 3);

m.process_event(42);
assert(m.current_state() == state_machine::Exit);
assert(value == 0);

m.process_event(42);
assert(m.current_state() == state_machine::Exit);
assert(value == 0);
#endif
return 0;
}

0 comments on commit 19092ce

Please sign in to comment.