Skip to content

Commit 6fb6f9d

Browse files
committed
Add track_object(), deprecate track_obj()
track_object() checks that the listed objects derive from sigc::trackable. Fixes #78
1 parent baab13f commit 6fb6f9d

File tree

2 files changed

+85
-40
lines changed

2 files changed

+85
-40
lines changed

sigc++/adaptors/track_obj.h

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,24 @@
2323
#include <sigc++/adaptors/tuple_visitor_visit_each.h>
2424
#include <sigc++/limit_reference.h>
2525
#include <sigc++/tuple-utils/tuple_for_each.h>
26+
#include <sigc++/trackable.h>
27+
#include <type_traits>
28+
#include <algorithm>
2629

2730
namespace sigc
2831
{
2932

30-
/** @defgroup track_obj track_obj()
31-
* sigc::track_obj() tracks trackable objects, referenced from a functor.
33+
/** @defgroup track_obj track_obj(), track_object()
34+
* sigc::track_object() tracks trackable objects, referenced from a functor.
3235
* It can be useful when you assign a C++11 lambda expression or a std::function<>
3336
* to a slot, or connect it to a signal, and the lambda expression or std::function<>
3437
* contains references to sigc::trackable derived objects.
3538
*
36-
* The functor returned by sigc::track_obj() is formally an adaptor, but it does
39+
* The functor returned by sigc::track_object() is formally an adaptor, but it does
3740
* not alter the signature, return type or behaviour of the supplied functor.
3841
*
42+
* track_obj() is a deprecated alternative to track_object().
43+
*
3944
* @par Example:
4045
* @code
4146
* struct bar : public sigc::trackable {};
@@ -45,18 +50,18 @@ namespace sigc
4550
* bar some_bar;
4651
* some_signal.connect([&some_bar](){ foo(some_bar); });
4752
* // NOT disconnected automatically when some_bar goes out of scope
48-
* some_signal.connect(sigc::track_obj([&some_bar](){ foo(some_bar); }, some_bar);
53+
* some_signal.connect(sigc::track_object([&some_bar](){ foo(some_bar); }, some_bar);
4954
* // disconnected automatically when some_bar goes out of scope
5055
* }
5156
* @endcode
5257
*
53-
* @newin{2,4}
54-
*
5558
* @ingroup adaptors
5659
*/
5760

58-
/** track_obj_functor wraps a functor and stores a reference to a trackable object.
59-
* Use the convenience function track_obj() to create an instance of track_obj_functor.
61+
/** %track_obj_functor wraps a functor and stores a reference to a trackable object.
62+
* Use the convenience function track_object() to create an instance of %track_obj_functor.
63+
*
64+
* track_obj() is a deprecated alternative to track_object().
6065
*
6166
* @tparam T_functor The type of functor to wrap.
6267
* @tparam T_obj The types of the trackable objects.
@@ -124,12 +129,14 @@ struct visitor<track_obj_functor<T_functor, T_obj...>>
124129
};
125130
#endif // DOXYGEN_SHOULD_SKIP_THIS
126131

132+
#ifndef SIGCXX_DISABLE_DEPRECATED
127133
/** Creates an adaptor of type sigc::track_obj_functor which wraps a functor.
128134
* @param func Functor that shall be wrapped.
129135
* @param obj Trackable objects.
130136
* @return Adaptor that executes func() on invocation.
131137
*
132138
* @newin{2,4}
139+
* @deprecated Use sigc::track_object() instead.
133140
*
134141
* @ingroup track_obj
135142
*/
@@ -139,6 +146,28 @@ track_obj(const T_functor& func, const T_obj&... obj)
139146
{
140147
return track_obj_functor<T_functor, T_obj...>(func, obj...);
141148
}
149+
#endif // SIGCXX_DISABLE_DEPRECATED
150+
151+
/** Creates an adaptor of type sigc::track_obj_functor which wraps a functor.
152+
* @param func Functor that shall be wrapped.
153+
* @param obj1 Trackable object, derived directly or indirectly from sigc::trackable.
154+
* @param objs Zero or more trackable objects, derived directly or indirectly from sigc::trackable.
155+
* @return Adaptor that executes func() on invocation.
156+
*
157+
* @newin{3,4}
158+
*
159+
* @ingroup track_obj
160+
*/
161+
template<typename T_functor, typename T_obj1, typename... T_objs>
162+
inline decltype(auto)
163+
track_object(const T_functor& func, const T_obj1& obj1, const T_objs&... objs)
164+
{
165+
static_assert(std::min<bool>({std::is_base_of<sigc::trackable, T_obj1>::value,
166+
std::is_base_of<sigc::trackable, T_objs>::value...}),
167+
"Each trackable object must be derived from sigc::trackable.");
168+
169+
return track_obj_functor<T_functor, T_obj1, T_objs...>(func, obj1, objs...);
170+
}
142171

143172
} /* namespace sigc */
144173

tests/test_track_obj.cc

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
*/
1818

1919
// The purpose of this test case is threefold.
20-
// - Test sigc::track_obj().
20+
// - Test sigc::track_obj() and sigc::track_object().
2121
// - Show that a slot with a C++11 lambda expression can be automatically
2222
// disconnected when an object derived from sigc::trackable is deleted,
23-
// provided sigc::track_obj() is used.
23+
// provided sigc::track_obj() or sigc::track_object() is used.
2424
// It shows that C++11 lambda expressions can replace the libsigc++ lambda
2525
// expressions, which have been removed.
2626
// See https://bugzilla.gnome.org/show_bug.cgi?id=672555
@@ -115,32 +115,38 @@ main(int argc, char* argv[])
115115
return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE;
116116

117117
sigc::slot<std::string(int)> sl1;
118+
sigc::slot<std::string(int)> sl2;
118119
{
119120
bar_group4 bar4;
120121
sl1 = sigc::track_obj(Functor1(bar4), bar4);
121-
result_stream << sl1(-2);
122-
util->check_result(result_stream, "negative");
122+
sl2 = sigc::track_object(Functor1(bar4), bar4);
123+
result_stream << sl1(-2) << ", " << sl2(2);
124+
util->check_result(result_stream, "negative, positive");
123125

124-
} // auto-disconnect sl1
126+
} // auto-disconnect sl1 and sl2
125127

126-
result_stream << sl1(-2);
127-
util->check_result(result_stream, "");
128+
result_stream << sl1(-2) << ", " << sl2(2);
129+
util->check_result(result_stream, ", ");
128130

129131
// Allocate on the heap. valgrind can then find erroneous memory accesses.
130132
// (There should be none, of course.)
131-
auto psl2 = new sigc::slot<std::string(int, std::string)>;
133+
auto psl3 = new sigc::slot<std::string(int, std::string)>;
134+
auto psl4 = new sigc::slot<std::string(int, std::string)>;
132135
auto pbar4 = new bar_group4;
133136
auto pbook4 = new book("A Book");
134-
*psl2 = sigc::track_obj(Functor2(*pbar4, *pbook4), *pbar4, *pbook4);
135-
result_stream << (*psl2)(0, "Book title: ");
136-
util->check_result(result_stream, "zero, Book title: A Book");
137+
*psl3 = sigc::track_obj(Functor2(*pbar4, *pbook4), *pbar4, *pbook4);
138+
*psl4 = sigc::track_object(Functor2(*pbar4, *pbook4), *pbar4, *pbook4);
139+
result_stream << (*psl3)(0, "Book title: ") << ", " << (*psl4)(1, "Title: ");
140+
util->check_result(result_stream, "zero, Book title: A Book, positive, Title: A Book");
137141

138-
delete pbook4; // auto-disconnect *psl2
142+
delete pbook4; // auto-disconnect *psl3 and *psl4
139143
pbook4 = nullptr;
140-
result_stream << (*psl2)(0, "Book title: ");
141-
util->check_result(result_stream, "");
142-
delete psl2;
143-
psl2 = nullptr;
144+
result_stream << (*psl3)(0, "Book title: ") << ", " << (*psl4)(1, "Title: ");
145+
util->check_result(result_stream, ", ");
146+
delete psl3;
147+
psl3 = nullptr;
148+
delete psl4;
149+
psl4 = nullptr;
144150
delete pbar4;
145151
pbar4 = nullptr;
146152

@@ -149,38 +155,47 @@ main(int argc, char* argv[])
149155
// auto-disconnect
150156
// If you want to auto-disconnect a slot with a C++11 lambda expression
151157
// that contains references to sigc::trackable-derived objects, you must use
152-
// sigc::track_obj().
153-
sigc::slot<void(std::ostringstream&)> sl10;
158+
// sigc::track_obj() or sigc::track_object().
159+
sigc::slot<void(std::ostringstream&)> sl11;
160+
sigc::slot<void(std::ostringstream&)> sl12;
154161
{
155162
book guest_book("karl");
156-
// sl1 = [&guest_book](std::ostringstream& stream){ stream << guest_book << "\n"; }; // no
157-
// auto-disconnect
158-
sl10 = sigc::track_obj(
163+
// no auto-disconnect
164+
// sl1 = [&guest_book](std::ostringstream& stream){ stream << guest_book << "\n"; };
165+
sl11 = sigc::track_obj(
166+
[&guest_book](std::ostringstream& stream) { stream << guest_book; }, guest_book);
167+
sl12 = sigc::track_object(
159168
[&guest_book](std::ostringstream& stream) { stream << guest_book; }, guest_book);
160-
sl10(result_stream);
161-
util->check_result(result_stream, "karl");
169+
sl11(result_stream);
170+
sl12(result_stream);
171+
util->check_result(result_stream, "karlkarl");
162172

163-
} // auto-disconnect sl10
173+
} // auto-disconnect sl11 and sl12
164174

165-
sl10(result_stream);
175+
sl11(result_stream);
176+
sl12(result_stream);
166177
util->check_result(result_stream, "");
167178

168179
// auto-disconnect
169-
sigc::slot<void()> sl20;
180+
sigc::slot<void()> sl21;
181+
sigc::slot<void()> sl22;
170182
{
171183
book guest_book("karl");
172184
// sl2 = [&guest_book] () { egon(guest_book); }; // no auto-disconnect
173185
// sl2 = std::bind(&egon, std::ref(guest_book)); // does not compile (gcc 4.6.3)
174-
sl20 = sigc::track_obj([&guest_book]() { egon(guest_book); }, guest_book);
175-
sl20();
176-
util->check_result(result_stream, "egon(string 'karl')");
186+
sl21 = sigc::track_obj([&guest_book]() { egon(guest_book); }, guest_book);
187+
sl22 = sigc::track_obj([&guest_book]() { egon(guest_book); }, guest_book);
188+
sl21();
189+
sl22();
190+
util->check_result(result_stream, "egon(string 'karl')egon(string 'egon was here')");
177191

178192
result_stream << static_cast<const std::string&>(guest_book);
179193
util->check_result(result_stream, "egon was here");
180194

181-
} // auto-disconnect sl20
195+
} // auto-disconnect sl21 and sl22
182196

183-
sl20();
197+
sl21();
198+
sl22();
184199
util->check_result(result_stream, "");
185200

186201
// Code example in the documentation sigc++/adaptors/track_obj.h.
@@ -194,8 +209,9 @@ main(int argc, char* argv[])
194209
// some_signal.connect(sigc::bind(&foo_group4, std::ref(some_bar))); // auto-disconnects,
195210
// but we prefer C++11 lambda
196211
some_signal.connect(sigc::track_obj([&some_bar]() { foo_group4(some_bar); }, some_bar));
212+
some_signal.connect(sigc::track_object([&some_bar]() { foo_group4(some_bar); }, some_bar));
197213
some_signal.emit();
198-
util->check_result(result_stream, "foo_group4(bar_group4&)");
214+
util->check_result(result_stream, "foo_group4(bar_group4&)foo_group4(bar_group4&)");
199215

200216
} // auto-disconnect the lambda expression
201217

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy