sigslot::observer issue when using a pointer
SebastianRedinger opened this issue · comments
Hi. First of all thanks for this great library.
I think I have found a issue while using sigslot::observer
. (Reproducable in MSVC2015 and MSVC2019)
This is my example code:
struct A : sigslot::observer {
void my_slot() { ; }
};
sigslot::signal<> my_signal;
// Example 1
{
A a;
my_signal.connect(&A::my_slot, &a); // <-- Call's overload with observer
}
// Works as expected: my_slot is not called
my_signal();
// Example 2
A* aptr2 = new A;
A& aptr2derefed = *aptr2;
my_signal.connect(&A::my_slot, &aptr2derefed); // <-- Call's overload with observer
delete aptr2;
// Works as expected: my_slot is not called
my_signal();
// Example 3
A* aptr = new A;
my_signal.connect(&A::my_slot, aptr); // <-- Call's overload without observer
delete aptr;
// my_slot gets called even though aptr is already deleted
my_signal();
Example 1 and 2 work as I expect and my_slot does not get called in example 3 however a differnet overload
of connect
gets called, where !trait::is_observer_v<Ptr>
is checked in std::enable_if
. This is an issue because
after aptr
is deleted and my_signal
gets emited my_slot
gets called on a dangling pointer.
It could be a misuse case on my side but I think it might be an error in is_observer_v
.
When you add a std::remove_reference_t
to is_observer_v
the issue seems to be fixed but I'm not sure if this causes any
unwanted side effects.
This is my proposed fix for this issue:
template <typename T>
constexpr bool is_observer_v = std::is_base_of<::sigslot::detail::observer_type,
std::remove_pointer_t<std::remove_reference_t<T>>>::value;
Fixed as per your suggestion, thanks!