Skip to content

Commit ef0f2fd

Browse files
marcobergaminkris-jusiak
authored andcommitted
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 7ca4d03)
1 parent 9d7cc3d commit ef0f2fd

File tree

2 files changed

+112
-1
lines changed

2 files changed

+112
-1
lines changed

Diff for: include/boost/sml.hpp

+28-1
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,16 @@ struct remove_reference<T &&> {
230230
};
231231
template <class T>
232232
using remove_reference_t = typename remove_reference<T>::type;
233+
template <class T>
234+
struct remove_pointer {
235+
using type = T;
236+
};
237+
template <class T>
238+
struct remove_pointer<T *> {
239+
using type = T;
240+
};
241+
template <class T>
242+
using remove_pointer_t = typename remove_pointer<T>::type;
233243
} // namespace aux
234244
namespace aux {
235245
using swallow = int[];
@@ -401,6 +411,14 @@ template <class T>
401411
constexpr T &try_get(const pool_type<T &> *object) {
402412
return object->value;
403413
}
414+
template <class T>
415+
const T *try_get(const pool_type<const T *> *object) {
416+
return object->value;
417+
}
418+
template <class T>
419+
T *try_get(const pool_type<T *> *object) {
420+
return object->value;
421+
}
404422
template <class T, class TPool>
405423
constexpr T &get(TPool &p) {
406424
return static_cast<pool_type<T> &>(p).value;
@@ -409,13 +427,22 @@ template <class T, class TPool>
409427
constexpr const T &cget(const TPool &p) {
410428
return static_cast<const pool_type<T> &>(p).value;
411429
}
430+
template <class T, class TPool>
431+
T *get(TPool *p) {
432+
return static_cast<pool_type<T> &>(p).value;
433+
}
434+
template <class T, class TPool>
435+
const T *cget(const TPool *p) {
436+
return static_cast<const pool_type<T> &>(p).value;
437+
}
412438
template <class... Ts>
413439
struct pool : pool_type<Ts>... {
414440
using boost_di_inject__ = type_list<Ts...>;
415441
constexpr pool() = default;
416442
constexpr explicit pool(Ts... ts) : pool_type<Ts>(ts)... {}
417443
template <class... TArgs>
418-
constexpr pool(init, const pool<TArgs...> &p) : pool_type<Ts>(try_get<aux::remove_const_t<aux::remove_reference_t<Ts>>>(&p))... {}
444+
constexpr pool(init, const pool<TArgs...> &p)
445+
: pool_type<Ts>(try_get<aux::remove_const_t<aux::remove_reference_t<aux::remove_pointer_t<Ts>>>>(&p))... {}
419446
template <class... TArgs>
420447
constexpr pool(const pool<TArgs...> &p) : pool_type<Ts>(init{}, p)... {}
421448
};

Diff for: test/ft/dependencies.cpp

+84
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,90 @@ test dependencies_smart_ptrs = [] {
179179
expect(sm.is(sml::X));
180180
};
181181

182+
test dependencies_with_reference = [] {
183+
struct Data {
184+
int m_member { 42 };
185+
};
186+
187+
struct c {
188+
auto operator()() noexcept {
189+
const auto action = [](Data& data) { expect(data.m_member == 42); };
190+
191+
using namespace sml;
192+
return make_transition_table(*idle + event<e1> / action = X);
193+
}
194+
};
195+
196+
Data data;
197+
sml::sm<c> sm{data};
198+
sm.process_event(e1{});
199+
expect(sm.is(sml::X));
200+
};
201+
202+
test dependencies_with_const_reference = [] {
203+
struct Data {
204+
int m_member { 42 };
205+
};
206+
207+
struct c {
208+
auto operator()() noexcept {
209+
const auto action = [](const Data& data) {
210+
expect(data.m_member == 42);
211+
};
212+
213+
using namespace sml;
214+
return make_transition_table(*idle + event<e1> / action = X);
215+
}
216+
};
217+
218+
Data data;
219+
sml::sm<c> sm{data};
220+
sm.process_event(e1{});
221+
expect(sm.is(sml::X));
222+
};
223+
224+
test dependencies_with_pointer = [] {
225+
struct Data {
226+
int m_member { 42 };
227+
};
228+
229+
struct c {
230+
auto operator()() noexcept {
231+
const auto action = [](Data* data) { expect(data->m_member == 42); };
232+
233+
using namespace sml;
234+
return make_transition_table(*idle + event<e1> / action = X);
235+
}
236+
};
237+
238+
Data data;
239+
sml::sm<c> sm{&data};
240+
sm.process_event(e1{});
241+
expect(sm.is(sml::X));
242+
};
243+
244+
test dependencies_with_const_pointer = [] {
245+
struct Data {
246+
int m_member { 42 };
247+
};
248+
249+
struct c {
250+
auto operator()() noexcept {
251+
const auto action = [](const Data* data) {
252+
expect(data->m_member == 42);
253+
};
254+
255+
using namespace sml;
256+
return make_transition_table(*idle + event<e1> / action = X);
257+
}
258+
};
259+
260+
Data data;
261+
sml::sm<c> sm{&data};
262+
sm.process_event(e1{});
263+
expect(sm.is(sml::X));
264+
};
265+
182266
#if (_MSC_VER >= 1910) // MSVC 2017
183267
test dependencies_multiple_subs = [] {
184268
struct update {

0 commit comments

Comments
 (0)