1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
/*
* Copyright 2013 - 2016, The libsigc++ Development Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SIGC_ADAPTORS_TRACK_OBJ_H
#define SIGC_ADAPTORS_TRACK_OBJ_H
#include <sigc++/adaptors/adapts.h>
#include <sigc++/adaptors/tuple_visitor_visit_each.h>
#include <sigc++/limit_reference.h>
#include <sigc++/tuple-utils/tuple_for_each.h>
#include <sigc++/trackable.h>
#include <type_traits>
#include <algorithm>
namespace sigc
{
/** @defgroup track_obj track_obj(), track_object()
* sigc::track_object() tracks trackable objects, referenced from a functor.
* It can be useful when you assign a C++11 lambda expression or a std::function<>
* to a slot, or connect it to a signal, and the lambda expression or std::function<>
* contains references to sigc::trackable derived objects.
*
* The functor returned by sigc::track_object() is formally an adaptor, but it does
* not alter the signature, return type or behaviour of the supplied functor.
*
* track_obj() is a deprecated alternative to track_object().
*
* @par Example:
* @code
* struct bar : public sigc::trackable {};
* sigc::signal<void()> some_signal;
* void foo(bar&);
* {
* bar some_bar;
* some_signal.connect([&some_bar](){ foo(some_bar); });
* // NOT disconnected automatically when some_bar goes out of scope
* some_signal.connect(sigc::track_object([&some_bar](){ foo(some_bar); }, some_bar);
* // disconnected automatically when some_bar goes out of scope
* }
* @endcode
*
* @ingroup adaptors
*/
/** %track_obj_functor wraps a functor and stores a reference to a trackable object.
* Use the convenience function track_object() to create an instance of %track_obj_functor.
*
* track_obj() is a deprecated alternative to track_object().
*
* @tparam T_functor The type of functor to wrap.
* @tparam T_obj The types of the trackable objects.
*
* @newin{2,4}
*
* @ingroup track_obj
*/
template<typename T_functor, typename... T_obj>
class track_obj_functor : public adapts<T_functor>
{
public:
/** Constructs a track_obj_functor object that wraps the passed functor and
* stores a reference to the passed trackable objects.
* @param func Functor.
* @param obj Trackable objects.
*/
explicit track_obj_functor(const T_functor& func, const T_obj&... obj)
: adapts<T_functor>(func), obj_(obj...)
{
}
/** Invokes the wrapped functor passing on the arguments.
* @param arg Arguments to be passed on to the functor.
* @return The return value of the functor invocation.
*/
template<typename... T_arg>
decltype(auto) operator()(T_arg&&... arg)
{
return std::invoke(this->functor_, std::forward<T_arg>(arg)...);
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// protected:
// public, so that visit_each() can access it.
std::tuple<limit_reference<const T_obj>...> obj_;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
}; // end class track_obj_functor
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// template specialization of visitor<>::do_visit_each<>(action, functor):
/** Performs a functor on each of the targets of a functor.
* The function overload for sigc::track_obj_functor performs a functor
* on the functor and on the trackable object instances stored in the
* sigc::track_obj_functor object.
*
* @newin{2,4}
*
* @ingroup track_obj
*/
template<typename T_functor, typename... T_obj>
struct visitor<track_obj_functor<T_functor, T_obj...>>
{
template<typename T_action>
static void do_visit_each(const T_action& action,
const track_obj_functor<T_functor, T_obj...>& target)
{
sigc::visit_each(action, target.functor_);
// Call sigc::visit_each(action, element) on each element in the
// target.obj_ tuple:
sigc::internal::tuple_for_each<internal::TupleVisitorVisitEach>(target.obj_, action);
}
};
#endif // DOXYGEN_SHOULD_SKIP_THIS
#ifndef SIGCXX_DISABLE_DEPRECATED
/** Creates an adaptor of type sigc::track_obj_functor which wraps a functor.
* @param func Functor that shall be wrapped.
* @param obj Trackable objects.
* @return Adaptor that executes func() on invocation.
*
* @newin{2,4}
* @deprecated Use sigc::track_object() instead.
*
* @ingroup track_obj
*/
template<typename T_functor, typename... T_obj>
inline decltype(auto)
track_obj(const T_functor& func, const T_obj&... obj)
{
return track_obj_functor<T_functor, T_obj...>(func, obj...);
}
#endif // SIGCXX_DISABLE_DEPRECATED
/** Creates an adaptor of type sigc::track_obj_functor which wraps a functor.
* @param func Functor that shall be wrapped.
* @param obj1 Trackable object, derived directly or indirectly from sigc::trackable.
* @param objs Zero or more trackable objects, derived directly or indirectly from sigc::trackable.
* @return Adaptor that executes func() on invocation.
*
* @newin{3,4}
*
* @ingroup track_obj
*/
template<typename T_functor, typename T_obj1, typename... T_objs>
inline decltype(auto)
track_object(const T_functor& func, const T_obj1& obj1, const T_objs&... objs)
{
static_assert(std::min<bool>({ std::is_base_of<sigc::trackable, T_obj1>::value,
std::is_base_of<sigc::trackable, T_objs>::value... }),
"Each trackable object must be derived from sigc::trackable.");
return track_obj_functor<T_functor, T_obj1, T_objs...>(func, obj1, objs...);
}
} /* namespace sigc */
#endif /* SIGC_ADAPTORS_TRACK_OBJ_H */
|