Open pettni opened 3 years ago
Same problem for me. I simply integrated struct my_logger
from logging.cpp
into the action_guards
example:
//
// Copyright (c) 2016-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/sml.hpp>
#include <cassert>
#include <iostream>
#include <typeinfo>
namespace sml = boost::sml;
namespace {
struct my_logger {
template <class SM, class TEvent>
void log_process_event(const TEvent&) {
printf("[%s][process_event] %s\n", sml::aux::get_type_name<SM>(), sml::aux::get_type_name<TEvent>());
}
template <class SM, class TGuard, class TEvent>
void log_guard(const TGuard&, const TEvent&, bool result) {
printf("[%s][guard] %s %s %s\n", sml::aux::get_type_name<SM>(), sml::aux::get_type_name<TGuard>(),
sml::aux::get_type_name<TEvent>(), (result ? "[OK]" : "[Reject]"));
}
template <class SM, class TAction, class TEvent>
void log_action(const TAction&, const TEvent&) {
printf("[%s][action] %s %s\n", sml::aux::get_type_name<SM>(), sml::aux::get_type_name<TAction>(),
sml::aux::get_type_name<TEvent>());
}
template <class SM, class TSrcState, class TDstState>
void log_state_change(const TSrcState& src, const TDstState& dst) {
printf("[%s][transition] %s -> %s\n", sml::aux::get_type_name<SM>(), src.c_str(), dst.c_str());
}
};
struct e1 {};
struct e2 {};
struct e3 {};
struct e4 {};
struct e5 {};
// Allow out of header implementation
bool guard2_impl(int i);
struct actions_guards {
using self = actions_guards;
auto operator()() {
using namespace sml;
auto guard1 = [] {
std::cout << "guard1" << std::endl;
return true;
};
auto guard2 = wrap(&guard2_impl);
auto action1 = [](auto e) { std::cout << "action1: " << typeid(e).name() << std::endl; };
struct action2 {
void operator()(int i) {
assert(42 == i);
std::cout << "action2" << std::endl;
}
};
// clang-format off
return make_transition_table(
*"idle"_s + event<e1> = "s1"_s
, "s1"_s + event<e2> [ guard1 ] / action1 = "s2"_s
, "s2"_s + event<e3> [ guard1 && ![] { return false;} ] / (action1, action2{}) = "s3"_s
, "s3"_s + event<e4> [ !guard1 || guard2 ] / (action1, [] { std::cout << "action3" << std::endl; }) = "s4"_s
, "s3"_s + event<e4> [ guard1 ] / ([] { std::cout << "action4" << std::endl; }, [this] { action4(); } ) = "s5"_s
, "s5"_s + event<e5> [ &self::guard3 ] / &self::action5 = X
);
// clang-format on
}
bool guard3(int i) const noexcept {
assert(42 == i);
std::cout << "guard3" << std::endl;
return true;
}
void action4() const { std::cout << "action4" << std::endl; }
void action5(int i, const e5&) {
assert(42 == i);
std::cout << "action5" << std::endl;
}
};
bool guard2_impl(int i) {
assert(42 == i);
std::cout << "guard2" << std::endl;
return false;
}
} // namespace
int main() {
my_logger logger;
actions_guards ag{};
sml::sm<actions_guards, sml::logger<my_logger>> sm{ag, 42, logger};
sm.process_event(e1{});
sm.process_event(e2{});
sm.process_event(e3{});
sm.process_event(e4{});
sm.process_event(e5{});
assert(sm.is(sml::X));
}
Compiler output:
In file included from sml/example/actions_guards.cpp:8:
sml/include/boost/sml.hpp: In instantiation of ‘void boost::ext::sml::v1_1_5::back::policies::log_guard(const boost::ext::sml::v1_1_5::aux::type<TLogger>&, TDeps&, const boost::ext::sml::v1_1_5::aux::zero_wrapper<TAction>&, const TEvent&, bool) [with SM = {anonymous}::actions_guards; TLogger = {anonymous}::my_logger; TDeps = boost::ext::sml::v1_1_5::aux::pool<int, {anonymous}::actions_guards&, {anonymous}::my_logger&>; TGuard = bool ({anonymous}::actions_guards::*)(int) const noexcept; TEvent = {anonymous}::e5]’:
sml/include/boost/sml.hpp:1939:35: required from ‘static auto boost::ext::sml::v1_1_5::front::call<TEvent, boost::ext::sml::v1_1_5::aux::type_list<TArgs ...>, TLogger>::execute_impl(const boost::ext::sml::v1_1_5::aux::type<bool>&, T, const TEvent&, SM&, TDeps&) [with TSM = {anonymous}::actions_guards; T = boost::ext::sml::v1_1_5::aux::zero_wrapper<bool ({anonymous}::actions_guards::*)(int) const noexcept, void>; SM = boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > >; TDeps = boost::ext::sml::v1_1_5::aux::pool<int, {anonymous}::actions_guards&, {anonymous}::my_logger&>; TEvent = {anonymous}::e5; Ts = {{anonymous}::actions_guards&, int}; TLogger = {anonymous}::my_logger]’
sml/include/boost/sml.hpp:1934:44: required from ‘static auto boost::ext::sml::v1_1_5::front::call<TEvent, boost::ext::sml::v1_1_5::aux::type_list<TArgs ...>, TLogger>::execute(T, const TEvent&, TSM&, TDeps&, TSubs&) [with T = boost::ext::sml::v1_1_5::aux::zero_wrapper<bool ({anonymous}::actions_guards::*)(int) const noexcept, void>; TSM = boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > >; TDeps = boost::ext::sml::v1_1_5::aux::pool<int, {anonymous}::actions_guards&, {anonymous}::my_logger&>; TSubs = boost::ext::sml::v1_1_5::aux::pool<boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > > >; TEvent = {anonymous}::e5; Ts = {{anonymous}::actions_guards&, int}; TLogger = {anonymous}::my_logger]’
sml/include/boost/sml.hpp:2489:72: required from ‘bool boost::ext::sml::v1_1_5::front::transition<boost::ext::sml::v1_1_5::front::state<T>, boost::ext::sml::v1_1_5::front::state<S2>, boost::ext::sml::v1_1_5::front::event<E>, G, A>::execute(const TEvent&, SM&, TDeps&, TSubs&, typename SM::state_t&, boost::ext::sml::v1_1_5::aux::false_type) [with TEvent = {anonymous}::e5; SM = boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > >; TDeps = boost::ext::sml::v1_1_5::aux::pool<int, {anonymous}::actions_guards&, {anonymous}::my_logger&>; TSubs = boost::ext::sml::v1_1_5::aux::pool<boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > > >; S1 = boost::ext::sml::v1_1_5::back::terminate_state; S2 = boost::ext::sml::v1_1_5::aux::string<char, 's', '5'>; E = {anonymous}::e5; G = boost::ext::sml::v1_1_5::aux::zero_wrapper<bool ({anonymous}::actions_guards::*)(int) const noexcept, void>; A = boost::ext::sml::v1_1_5::aux::zero_wrapper<void ({anonymous}::actions_guards::*)(int, const {anonymous}::e5&), void>; typename SM::state_t = unsigned char; boost::ext::sml::v1_1_5::aux::false_type = boost::ext::sml::v1_1_5::aux::integral_constant<bool, false>]’
sml/include/boost/sml.hpp:917:48: required from ‘static bool boost::ext::sml::v1_1_5::back::transitions<T>::execute(const TEvent&, SM&, TDeps&, TSubs&, typename SM::state_t&) [with TEvent = {anonymous}::e5; SM = boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > >; TDeps = boost::ext::sml::v1_1_5::aux::pool<int, {anonymous}::actions_guards&, {anonymous}::my_logger&>; TSubs = boost::ext::sml::v1_1_5::aux::pool<boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > > >; T = boost::ext::sml::v1_1_5::front::transition<boost::ext::sml::v1_1_5::front::state<boost::ext::sml::v1_1_5::back::terminate_state>, boost::ext::sml::v1_1_5::front::state<boost::ext::sml::v1_1_5::aux::string<char, 's', '5'> >, boost::ext::sml::v1_1_5::front::event<{anonymous}::e5>, boost::ext::sml::v1_1_5::aux::zero_wrapper<bool ({anonymous}::actions_guards::*)(int) const noexcept, void>, boost::ext::sml::v1_1_5::aux::zero_wrapper<void ({anonymous}::actions_guards::*)(int, const {anonymous}::e5&), void> >; typename SM::state_t = unsigned char]’
sml/include/boost/sml.hpp:1115:39: required from ‘static bool boost::ext::sml::v1_1_5::back::policies::jump_table::dispatch(sm_impl&, State&, const TEvent&, TDeps&, TSubs&, const boost::ext::sml::v1_1_5::aux::type_list<T7s ...>&) [with int <anonymous> = 0; TMappings = boost::ext::sml::v1_1_5::back::get_event_mapping_impl_helper<{anonymous}::e5, boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > >::mappings>; sm_impl = boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > >; State = unsigned char; TEvent = {anonymous}::e5; TDeps = boost::ext::sml::v1_1_5::aux::pool<int, {anonymous}::actions_guards&, {anonymous}::my_logger&>; TSubs = boost::ext::sml::v1_1_5::aux::pool<boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > > >; TStates = {boost::ext::sml::v1_1_5::aux::string<char, 'i', 'd', 'l', 'e'>, boost::ext::sml::v1_1_5::aux::string<char, 's', '1'>, boost::ext::sml::v1_1_5::aux::string<char, 's', '2'>, boost::ext::sml::v1_1_5::aux::string<char, 's', '3'>, boost::ext::sml::v1_1_5::aux::string<char, 's', '4'>, boost::ext::sml::v1_1_5::aux::string<char, 's', '5'>, boost::ext::sml::v1_1_5::back::terminate_state}]’
sml/include/boost/sml.hpp:1500:55: required from ‘bool boost::ext::sml::v1_1_5::back::sm_impl< <template-parameter-1-1> >::process_event_impl(const TEvent&, TDeps&, TSubs&, const boost::ext::sml::v1_1_5::aux::type_list<TStates ...>&, boost::ext::sml::v1_1_5::aux::index_sequence<0>) [with TMappings = boost::ext::sml::v1_1_5::back::get_event_mapping_impl_helper<{anonymous}::e5, boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > >::mappings>; TEvent = {anonymous}::e5; TDeps = boost::ext::sml::v1_1_5::aux::pool<int, {anonymous}::actions_guards&, {anonymous}::my_logger&>; TSubs = boost::ext::sml::v1_1_5::aux::pool<boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > > >; TStates = {boost::ext::sml::v1_1_5::aux::string<char, 'i', 'd', 'l', 'e'>, boost::ext::sml::v1_1_5::aux::string<char, 's', '1'>, boost::ext::sml::v1_1_5::aux::string<char, 's', '2'>, boost::ext::sml::v1_1_5::aux::string<char, 's', '3'>, boost::ext::sml::v1_1_5::aux::string<char, 's', '4'>, boost::ext::sml::v1_1_5::aux::string<char, 's', '5'>, boost::ext::sml::v1_1_5::back::terminate_state}; TSM = boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> >]’
sml/include/boost/sml.hpp:1527:41: required from ‘bool boost::ext::sml::v1_1_5::back::sm_impl< <template-parameter-1-1> >::process_event_except_imp(const TEvent&, TDeps&, TSubs&, boost::ext::sml::v1_1_5::aux::false_type) [with TMappings = boost::ext::sml::v1_1_5::back::get_event_mapping_impl_helper<{anonymous}::e5, boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > >::mappings>; TEvent = {anonymous}::e5; TDeps = boost::ext::sml::v1_1_5::aux::pool<int, {anonymous}::actions_guards&, {anonymous}::my_logger&>; TSubs = boost::ext::sml::v1_1_5::aux::pool<boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > > >; TSM = boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> >; boost::ext::sml::v1_1_5::aux::false_type = boost::ext::sml::v1_1_5::aux::integral_constant<bool, false>]’
sml/include/boost/sml.hpp:1440:90: required from ‘bool boost::ext::sml::v1_1_5::back::sm_impl< <template-parameter-1-1> >::process_internal_events(const TEvent&, TDeps&, TSubs&) [with TEvent = {anonymous}::e5; TDeps = boost::ext::sml::v1_1_5::aux::pool<int, {anonymous}::actions_guards&, {anonymous}::my_logger&>; TSubs = boost::ext::sml::v1_1_5::aux::pool<boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > > >; typename boost::ext::sml::v1_1_5::aux::enable_if<(boost::ext::sml::v1_1_5::aux::integral_constant<bool, __is_base_of(typename boost::ext::sml::v1_1_5::back::event_type<TEvent>::generic_t, typename boost::ext::sml::v1_1_5::aux::apply<boost::ext::sml::v1_1_5::aux::inherit, typename boost::ext::sml::v1_1_5::aux::apply<boost::ext::sml::v1_1_5::aux::unique_t, typename boost::ext::sml::v1_1_5::aux::join<typename boost::ext::sml::v1_1_5::aux::apply<boost::ext::sml::v1_1_5::aux::unique_t, typename boost::ext::sml::v1_1_5::aux::apply<boost::ext::sml::v1_1_5::back::get_sub_internal_events, decltype((declval<typename TSM::sm>)().operator()())>::type>::type, typename boost::ext::sml::v1_1_5::aux::apply<boost::ext::sml::v1_1_5::back::get_all_events, decltype((declval<typename TSM::sm>)().operator()())>::type>::type>::type>::type)>::value && (! boost::ext::sml::v1_1_5::aux::integral_constant<bool, __is_base_of(typename boost::ext::sml::v1_1_5::back::event_type<TEvent>::mapped_t, typename boost::ext::sml::v1_1_5::aux::apply<boost::ext::sml::v1_1_5::aux::inherit, typename boost::ext::sml::v1_1_5::aux::apply<boost::ext::sml::v1_1_5::aux::unique_t, typename boost::ext::sml::v1_1_5::aux::join<typename boost::ext::sml::v1_1_5::aux::apply<boost::ext::sml::v1_1_5::aux::unique_t, typename boost::ext::sml::v1_1_5::aux::apply<boost::ext::sml::v1_1_5::back::get_sub_internal_events, decltype((declval<typename TSM::sm>)().operator()())>::type>::type, typename boost::ext::sml::v1_1_5::aux::apply<boost::ext::sml::v1_1_5::back::get_all_events, decltype((declval<typename TSM::sm>)().operator()())>::type>::type>::type>::type)>::value)), int>::type <anonymous> = 0; TSM = boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> >]’
sml/include/boost/sml.hpp:1398:43: required from ‘bool boost::ext::sml::v1_1_5::back::sm_impl< <template-parameter-1-1> >::process_event(const TEvent&, TDeps&, TSubs&) [with TEvent = {anonymous}::e5; TDeps = boost::ext::sml::v1_1_5::aux::pool<int, {anonymous}::actions_guards&, {anonymous}::my_logger&>; TSubs = boost::ext::sml::v1_1_5::aux::pool<boost::ext::sml::v1_1_5::back::sm_impl<boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> > > >; TSM = boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> >]’
sml/include/boost/sml.hpp:1719:58: required from ‘bool boost::ext::sml::v1_1_5::back::sm< <template-parameter-1-1> >::process_event(const TEvent&) [with TEvent = {anonymous}::e5; typename boost::ext::sml::v1_1_5::aux::enable_if<boost::ext::sml::v1_1_5::aux::integral_constant<bool, __is_base_of(TEvent, boost::ext::sml::v1_1_5::back::sm< <template-parameter-1-1> >::events_ids)>::value, int>::type <anonymous> = 0; TSM = boost::ext::sml::v1_1_5::back::sm_policy<{anonymous}::actions_guards, boost::ext::sml::v1_1_5::back::policies::logger<{anonymous}::my_logger> >]’
sml/example/actions_guards.cpp:112:19: required from here
sml/include/boost/sml.hpp:1239:92: error: ‘const struct boost::ext::sml::v1_1_5::aux::zero_wrapper<bool ({anonymous}::actions_guards::*)(int) const noexcept, void>’ has no member named ‘get’
compilation terminated due to -Wfatal-errors.
At least it should be written in documentation that it doesn't work?
Also suffering from this issue.. any tips?
Also suffering from this issue.. any tips?
I don't use member functions anymore. For guards and actions I use functors now:
struct MyFsm {
/*
* guards
*/
struct error {
bool operator()(auto const &event)
{
return ...;
}
};
/*
* actions
*/
struct updateStatus {
void operator()(Dependencies &d)
{
d.myHandler.updateStatus();
}
};
auto operator()()
{
using namespace sml;
return make_transition_table(
...
}
};
Thanks for creating this library. I ran into an issue when trying to implement logging.
Expected Behavior
Logging should work when using member function guards and actions.
Actual Behavior
Compilation error:
Steps to Reproduce the Problem
This is a modified version of the
logging.cpp
exampleWorkaround
Wrap the member action or guard in a lambda instead of using the
&self::
syntax.Specifications