Skip to content

Commit

Permalink
fixed #603: not all zero wrappers define a get() method, which breaks…
Browse files Browse the repository at this point in the history
… logging in some cases
  • Loading branch information
devzeb authored and kris-jusiak committed Mar 7, 2024
1 parent 78e0640 commit 7581bc1
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 13 deletions.
36 changes: 24 additions & 12 deletions include/boost/sml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,52 +496,64 @@ struct zero_wrapper : TExpr {
};
template <class R, class TBase, class... TArgs, class T>
struct zero_wrapper<R (TBase::*)(TArgs...), T> {
constexpr explicit zero_wrapper(R (TBase::*ptr)(TArgs...)) : ptr{ptr} {}
using type = R (TBase::*)(TArgs...);
constexpr explicit zero_wrapper(type ptr) : ptr{ptr} {}
constexpr auto operator()(TBase &self, TArgs... args) { return (self.*ptr)(args...); }
constexpr type get() const { return ptr; }

private:
R (TBase::*ptr)(TArgs...){};
type ptr{};
};
template <class R, class TBase, class... TArgs, class T>
struct zero_wrapper<R (TBase::*)(TArgs...) const, T> {
constexpr explicit zero_wrapper(R (TBase::*ptr)(TArgs...) const) : ptr{ptr} {}
using type = R (TBase::*)(TArgs...) const;
constexpr explicit zero_wrapper(type ptr) : ptr{ptr} {}
constexpr auto operator()(TBase &self, TArgs... args) { return (self.*ptr)(args...); }
constexpr type get() const { return ptr; }

private:
R (TBase::*ptr)(TArgs...) const {};
type ptr{};
};
template <class R, class... TArgs, class T>
struct zero_wrapper<R (*)(TArgs...), T> {
explicit zero_wrapper(R (*ptr)(TArgs...)) : ptr{ptr} {}
using type = R (*)(TArgs...);
explicit zero_wrapper(type ptr) : ptr{ptr} {}
constexpr auto operator()(TArgs... args) { return (*ptr)(args...); }
constexpr type get() const { return ptr; }

private:
R (*ptr)(TArgs...){};
type ptr{};
};
#if defined(__cpp_noexcept_function_type)
template <class R, class TBase, class... TArgs, class T>
struct zero_wrapper<R (TBase::*)(TArgs...) noexcept, T> {
constexpr explicit zero_wrapper(R (TBase::*ptr)(TArgs...) noexcept) : ptr{ptr} {}
using type = R (TBase::*)(TArgs...) noexcept;
constexpr explicit zero_wrapper(type ptr) : ptr{ptr} {}
constexpr auto operator()(TBase &self, TArgs... args) { return (self.*ptr)(args...); }
constexpr type get() const { return ptr; }

private:
R (TBase::*ptr)(TArgs...) noexcept {};
type ptr {};
};
template <class R, class TBase, class... TArgs, class T>
struct zero_wrapper<R (TBase::*)(TArgs...) const noexcept, T> {
constexpr explicit zero_wrapper(R (TBase::*ptr)(TArgs...) const noexcept) : ptr{ptr} {}
using type = R (TBase::*)(TArgs...) const noexcept;
constexpr explicit zero_wrapper(type ptr) : ptr{ptr} {}
constexpr auto operator()(TBase &self, TArgs... args) { return (self.*ptr)(args...); }
constexpr type get() const { return ptr; }

private:
R (TBase::*ptr)(TArgs...) const noexcept {};
type ptr {};
};
template <class R, class... TArgs, class T>
struct zero_wrapper<R (*)(TArgs...) noexcept, T> {
explicit zero_wrapper(R (*ptr)(TArgs...) noexcept) : ptr{ptr} {}
using type = R (*)(TArgs...) noexcept;
explicit zero_wrapper(type ptr) : ptr{ptr} {}
constexpr auto operator()(TArgs... args) { return (*ptr)(args...); }
constexpr type get() const { return ptr; }

private:
R (*ptr)(TArgs...) noexcept {};
type ptr {};
};
#endif
template <class, class>
Expand Down
48 changes: 47 additions & 1 deletion test/ft/policies_logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <algorithm>
#include <boost/sml.hpp>
#include <iomanip>
#include <queue>
#include <sstream>
#include <vector>

Expand Down Expand Up @@ -37,7 +38,8 @@ struct my_logger {
template <class SM, class TAction, class TEvent>
void log_action(const TAction&, const TEvent&) {
std::stringstream sstr;
sstr << "[" << sml::aux::get_type_name<SM>() << "] " << "/ " << sml::aux::get_type_name<TAction>();
sstr << "[" << sml::aux::get_type_name<SM>() << "] "
<< "/ " << sml::aux::get_type_name<TAction>();
const auto str = sstr.str();
messages_out.push_back(str);
}
Expand Down Expand Up @@ -248,4 +250,48 @@ test log_sub_sm_mix = [] {
expect(std::equal(logger.messages_out.begin(), logger.messages_out.end(), messages_expected.begin()));
};

struct dependency_class_with_member_function_action {
void member_function() {}
};

struct c_log_sm_member_function_as_action {
auto operator()() {
using namespace sml;

using cls = dependency_class_with_member_function_action;

// clang-format off
return make_transition_table(
*"idle"_s + event<e1> / &cls::member_function = s1
, s1 + event<e2> = X
);
// clang-format on
}
};

test log_member_function_pointer_and_process_queue = [] {
// clang-format off
std::vector<std::string> messages_expected = {
"[c_log_sm_member_function_as_action] on_entry"
, "[c_log_sm_member_function_as_action] e1"
, "[c_log_sm_member_function_as_action] idle -> s1_label"
, "[c_log_sm_member_function_as_action] / void (dependency_class_with_member_function_action::*)()"
, "[c_log_sm_member_function_as_action] e2"
, "[c_log_sm_member_function_as_action] s1_label -> terminate"
};
// clang-format on

dependency_class_with_member_function_action dep;

my_logger logger;
sml::sm<c_log_sm_member_function_as_action, sml::logger<my_logger>, sml::process_queue<std::queue>> sm{logger, dep};

sm.process_event(e1{});
sm.process_event(e2{});
sm.process_event(e3{});

expect(logger.messages_out.size() == messages_expected.size());
expect(std::equal(logger.messages_out.begin(), logger.messages_out.end(), messages_expected.begin()));
};

#endif

0 comments on commit 7581bc1

Please sign in to comment.