Skip to content

Commit a460965

Browse files
author
Kjell Ahlstedt
committed
slot_rep: Make destructor, destroy() and dup() virtual
* sigc++/functors/slot_base.h: * sigc++/functors/slot.h: Make ~slot_rep(), slot_rep::destroy() and slot_rep::dup() virtual. Bug 777618
1 parent 714caf1 commit a460965

File tree

2 files changed

+19
-46
lines changed

2 files changed

+19
-46
lines changed

sigc++/functors/slot.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ template <typename T_functor>
4343
struct typed_slot_rep : public slot_rep
4444
{
4545
private:
46-
using self = typed_slot_rep<T_functor>;
47-
4846
/* Use an adaptor type so that arguments can be passed as const references
4947
* through explicit template instantiation from slot_call#::call_it() */
5048
using adaptor_type = typename adaptor_trait<T_functor>::adaptor_type;
@@ -58,13 +56,13 @@ struct typed_slot_rep : public slot_rep
5856
* @param functor The functor contained by the new slot_rep object.
5957
*/
6058
inline explicit typed_slot_rep(const T_functor& functor)
61-
: slot_rep(nullptr, &destroy, &dup), functor_(std::make_unique<adaptor_type>(functor))
59+
: slot_rep(nullptr), functor_(std::make_unique<adaptor_type>(functor))
6260
{
6361
sigc::visit_each_trackable(slot_do_bind(this), *functor_);
6462
}
6563

6664
inline typed_slot_rep(const typed_slot_rep& src)
67-
: slot_rep(src.call_, &destroy, &dup), functor_(std::make_unique<adaptor_type>(*src.functor_))
65+
: slot_rep(src.call_), functor_(std::make_unique<adaptor_type>(*src.functor_))
6866
{
6967
sigc::visit_each_trackable(slot_do_bind(this), *functor_);
7068
}
@@ -74,24 +72,25 @@ struct typed_slot_rep : public slot_rep
7472
typed_slot_rep(typed_slot_rep&& src) = delete;
7573
typed_slot_rep& operator=(typed_slot_rep&& src) = delete;
7674

77-
inline ~typed_slot_rep()
75+
~typed_slot_rep() override
7876
{
79-
call_ = nullptr;
80-
destroy_ = nullptr;
81-
sigc::visit_each_trackable(slot_do_unbind(this), *functor_);
77+
// Call destroy() non-virtually.
78+
// It's unwise to make virtual calls in a constructor or destructor.
79+
typed_slot_rep::destroy();
8280
}
8381

8482
private:
8583
/** Detaches the stored functor from the other referred trackables and destroys it.
8684
* This does not destroy the base slot_rep object.
8785
*/
88-
static void destroy(slot_rep* data)
86+
void destroy() override
8987
{
90-
auto self_ = static_cast<self*>(data);
91-
self_->call_ = nullptr;
92-
self_->destroy_ = nullptr;
93-
sigc::visit_each_trackable(slot_do_unbind(self_), *self_->functor_);
94-
self_->functor_.reset(nullptr);
88+
call_ = nullptr;
89+
if (functor_)
90+
{
91+
sigc::visit_each_trackable(slot_do_unbind(this), *functor_);
92+
functor_.reset(nullptr);
93+
}
9594
/* don't call disconnect() here: destroy() is either called
9695
* a) from the parent itself (in which case disconnect() leads to a segfault) or
9796
* b) from a parentless slot (in which case disconnect() does nothing)
@@ -103,7 +102,7 @@ struct typed_slot_rep : public slot_rep
103102
* slot_rep object is registered in the referred trackables.
104103
* @return A deep copy of the slot_rep object.
105104
*/
106-
static slot_rep* dup(slot_rep* a_rep) { return new self(*static_cast<self*>(a_rep)); }
105+
slot_rep* dup() const override { return new typed_slot_rep(*this); }
107106
};
108107

109108
/** Abstracts functor execution.

sigc++/functors/slot_base.h

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,14 @@ struct SIGC_API slot_rep : public trackable
6666
* down dereferencing of slot list iterators. Martin. */
6767
// TODO: Try this now? murrayc.
6868

69-
using hook_dup = slot_rep* (*)(slot_rep*);
70-
71-
using func_slot_rep_destroy_notify = void (*)(slot_rep* data);
72-
73-
inline slot_rep(hook call__, func_slot_rep_destroy_notify destroy__, hook_dup dup__) noexcept
69+
inline slot_rep(hook call__) noexcept
7470
: call_(call__),
7571
cleanup_(nullptr),
76-
parent_(nullptr),
77-
destroy_(destroy__),
78-
dup_(dup__)
72+
parent_(nullptr)
7973
{
8074
}
8175

82-
inline ~slot_rep() { destroy(); }
76+
virtual ~slot_rep() {}
8377

8478
// only MSVC needs this to guarantee that all new/delete are executed from the DLL module
8579
#ifdef SIGC_NEW_DELETE_IN_LIBRARY_ONLY
@@ -89,19 +83,12 @@ struct SIGC_API slot_rep : public trackable
8983

9084
/** Destroys the slot_rep object (but doesn't delete it).
9185
*/
92-
inline void destroy()
93-
{
94-
if (destroy_)
95-
(*destroy_)(this);
96-
}
86+
virtual void destroy() = 0;
9787

9888
/** Makes a deep copy of the slot_rep object.
9989
* @return A deep copy of the slot_rep object.
10090
*/
101-
inline slot_rep* dup() const
102-
{
103-
return (*dup_)(const_cast<slot_rep*>(this));
104-
}
91+
virtual slot_rep* dup() const = 0;
10592

10693
/** Set the parent with a callback.
10794
* slots have one parent exclusively.
@@ -148,19 +135,6 @@ struct SIGC_API slot_rep : public trackable
148135

149136
/** Parent object whose callback cleanup_ is executed on notification. */
150137
notifiable* parent_;
151-
152-
protected:
153-
/// Callback that detaches the slot_rep object from referred trackables and destroys it.
154-
/* This could be a replaced by a virtual dtor. However, since this struct is
155-
* crucial for the efficiency of the whole library, we want to avoid this.
156-
*/
157-
func_slot_rep_destroy_notify destroy_;
158-
159-
private:
160-
/** Callback that makes a deep copy of the slot_rep object.
161-
* @return A deep copy of the slot_rep object.
162-
*/
163-
hook_dup dup_;
164138
};
165139

166140
/** Functor used to add a dependency to a trackable.

0 commit comments

Comments
 (0)