From ee2546ed899b7c29e1e0a683fc82f1d3b783dd28 Mon Sep 17 00:00:00 2001 From: Marco Bergamin Date: Tue, 2 Jun 2020 07:21:23 -0500 Subject: [PATCH] Fix bug in dep resolution when requesting a "const T*" after providing a "T*" Before this fix, if a T* was injected as depedency, requesting a const T* will result in a invalid nullptr. Four unit tests added. (cherry picked from commit 7ca4d03178a7f1b301975ae398a45e3f55cbb580) --- include/boost/sml.hpp | 29 +++++++++++++- test/ft/dependencies.cpp | 84 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/include/boost/sml.hpp b/include/boost/sml.hpp index 2a5dac92..ca00ff43 100644 --- a/include/boost/sml.hpp +++ b/include/boost/sml.hpp @@ -230,6 +230,16 @@ struct remove_reference { }; template using remove_reference_t = typename remove_reference::type; +template +struct remove_pointer { + using type = T; +}; +template +struct remove_pointer { + using type = T; +}; +template +using remove_pointer_t = typename remove_pointer::type; } // namespace aux namespace aux { using swallow = int[]; @@ -401,6 +411,14 @@ template constexpr T &try_get(const pool_type *object) { return object->value; } +template +const T *try_get(const pool_type *object) { + return object->value; +} +template +T *try_get(const pool_type *object) { + return object->value; +} template constexpr T &get(TPool &p) { return static_cast &>(p).value; @@ -409,13 +427,22 @@ template constexpr const T &cget(const TPool &p) { return static_cast &>(p).value; } +template +T *get(TPool *p) { + return static_cast &>(p).value; +} +template +const T *cget(const TPool *p) { + return static_cast &>(p).value; +} template struct pool : pool_type... { using boost_di_inject__ = type_list; constexpr pool() = default; constexpr explicit pool(Ts... ts) : pool_type(ts)... {} template - constexpr pool(init, const pool &p) : pool_type(try_get>>(&p))... {} + constexpr pool(init, const pool &p) + : pool_type(try_get>>>(&p))... {} template constexpr pool(const pool &p) : pool_type(init{}, p)... {} }; diff --git a/test/ft/dependencies.cpp b/test/ft/dependencies.cpp index f74bf96d..ae8f7131 100644 --- a/test/ft/dependencies.cpp +++ b/test/ft/dependencies.cpp @@ -179,6 +179,90 @@ test dependencies_smart_ptrs = [] { expect(sm.is(sml::X)); }; +test dependencies_with_reference = [] { + struct Data { + int m_member { 42 }; + }; + + struct c { + auto operator()() noexcept { + const auto action = [](Data& data) { expect(data.m_member == 42); }; + + using namespace sml; + return make_transition_table(*idle + event / action = X); + } + }; + + Data data; + sml::sm sm{data}; + sm.process_event(e1{}); + expect(sm.is(sml::X)); +}; + +test dependencies_with_const_reference = [] { + struct Data { + int m_member { 42 }; + }; + + struct c { + auto operator()() noexcept { + const auto action = [](const Data& data) { + expect(data.m_member == 42); + }; + + using namespace sml; + return make_transition_table(*idle + event / action = X); + } + }; + + Data data; + sml::sm sm{data}; + sm.process_event(e1{}); + expect(sm.is(sml::X)); +}; + +test dependencies_with_pointer = [] { + struct Data { + int m_member { 42 }; + }; + + struct c { + auto operator()() noexcept { + const auto action = [](Data* data) { expect(data->m_member == 42); }; + + using namespace sml; + return make_transition_table(*idle + event / action = X); + } + }; + + Data data; + sml::sm sm{&data}; + sm.process_event(e1{}); + expect(sm.is(sml::X)); +}; + +test dependencies_with_const_pointer = [] { + struct Data { + int m_member { 42 }; + }; + + struct c { + auto operator()() noexcept { + const auto action = [](const Data* data) { + expect(data->m_member == 42); + }; + + using namespace sml; + return make_transition_table(*idle + event / action = X); + } + }; + + Data data; + sml::sm sm{&data}; + sm.process_event(e1{}); + expect(sm.is(sml::X)); +}; + #if (_MSC_VER >= 1910) // MSVC 2017 test dependencies_multiple_subs = [] { struct update {