1 // Boost.Signals library
3 // Copyright (C) 2001-2002 Doug Gregor (gregod@cs.rpi.edu)
5 // Permission to copy, use, sell and distribute this software is granted
6 // provided this copyright notice appears in all copies.
7 // Permission to modify the code and to distribute modified code is granted
8 // provided this copyright notice appears in all copies, and a notice
9 // that the code was modified is included with the copyright notice.
11 // This software is provided "as is" without express or implied warranty,
12 // and with no claim as to its suitability for any purpose.
14 // For more information, see http://www.boost.org
16 // This file intentionally does not have include guards, because it is meant
17 // to be included multiple times (one for each signalN class). The
18 // BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED macro merely serves to
19 // suppress reinclusion of the files that this header depends on.
21 #ifndef BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
22 #define BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
23 # include <boost/config.hpp>
24 # include <boost/signals/connection.hpp>
25 # include <boost/utility.hpp>
26 # include <boost/ref.hpp>
27 # include <boost/signals/slot.hpp>
28 # include <boost/last_value.hpp>
29 # include <boost/signals/detail/signal_base.hpp>
30 # include <boost/signals/detail/slot_call_iterator.hpp>
32 # include <functional>
35 #endif // !BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
37 // Include the appropriate functionN header
38 #define BOOST_SIGNAL_FUNCTION_N_HEADER BOOST_JOIN(<boost/function/function,BOOST_SIGNALS_NUM_ARGS.hpp>)
39 #include BOOST_SIGNAL_FUNCTION_N_HEADER
41 // Determine if a comma should follow a listing of the arguments/parameters
42 #if BOOST_SIGNALS_NUM_ARGS == 0
43 # define BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
45 # define BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS ,
46 #endif // BOOST_SIGNALS_NUM_ARGS > 0
48 // Define class names used
49 #define BOOST_SIGNALS_SIGNAL BOOST_JOIN(signal,BOOST_SIGNALS_NUM_ARGS)
50 #define BOOST_SIGNALS_FUNCTION BOOST_JOIN(function,BOOST_SIGNALS_NUM_ARGS)
51 #define BOOST_SIGNALS_ARGS_STRUCT BOOST_JOIN(args,BOOST_SIGNALS_NUM_ARGS)
52 #define BOOST_SIGNALS_CALL_BOUND BOOST_JOIN(call_bound,BOOST_SIGNALS_NUM_ARGS)
54 // Define commonly-used instantiations
55 #define BOOST_SIGNALS_ARGS_STRUCT_INST \
56 BOOST_SIGNALS_NAMESPACE::detail::BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>
59 namespace BOOST_SIGNALS_NAMESPACE {
61 // Holds the arguments for a bound slot call in a single place
62 template<BOOST_SIGNALS_TEMPLATE_PARMS
63 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
65 struct BOOST_SIGNALS_ARGS_STRUCT {
66 BOOST_SIGNALS_ARGS_STRUCT(BOOST_SIGNALS_COPY_PARMS)
67 BOOST_SIGNALS_INIT_ARGS
71 BOOST_SIGNALS_ARGS_AS_MEMBERS
74 // Function object that calls the function object given to it, passing
75 // the bound arguments along to that underlying function object
77 struct BOOST_SIGNALS_CALL_BOUND {
78 template<BOOST_SIGNALS_TEMPLATE_PARMS
79 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
82 typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
87 typedef R result_type;
90 caller(args_type a) : args(a) {}
92 template<typename Pair>
93 R operator()(const Pair& slot) const
95 F* target = const_cast<F*>(any_cast<F>(&slot.second.second));
96 return (*target)(BOOST_SIGNALS_BOUND_ARGS);
102 struct BOOST_SIGNALS_CALL_BOUND<void> {
103 template<BOOST_SIGNALS_TEMPLATE_PARMS
104 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
107 typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
112 typedef unusable result_type;
114 caller(args_type a) : args(a) {}
116 template<typename Pair>
117 unusable operator()(const Pair& slot) const
119 F* target = const_cast<F*>(any_cast<F>(&slot.second.second));
120 (*target)(BOOST_SIGNALS_BOUND_ARGS);
125 } // namespace detail
126 } // namespace BOOST_SIGNALS_NAMESPACE
128 // The actual signalN class
131 BOOST_SIGNALS_TEMPLATE_PARMS
132 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
133 typename Combiner = last_value<R>,
134 typename Group = int,
135 typename GroupCompare = std::less<Group>,
136 typename SlotFunction = BOOST_SIGNALS_FUNCTION<
137 R BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
138 BOOST_SIGNALS_TEMPLATE_ARGS>
140 class BOOST_SIGNALS_SIGNAL :
141 public BOOST_SIGNALS_NAMESPACE::detail::signal_base, // management of slot list
142 public BOOST_SIGNALS_NAMESPACE::trackable // signals are trackable
145 // The slot function type
146 typedef SlotFunction slot_function_type;
148 // Result type of a slot
149 typedef typename BOOST_SIGNALS_NAMESPACE::detail::slot_result_type<R>::type
153 BOOST_SIGNALS_ARG_TYPES
155 #if BOOST_SIGNALS_NUM_ARGS == 1
156 typedef T1 argument_type;
157 #elif BOOST_SIGNALS_NUM_ARGS == 2
158 typedef T1 first_argument_type;
159 typedef T2 second_argument_type;
163 // The real slot name comparison object type
164 typedef BOOST_SIGNALS_NAMESPACE::detail::any_bridge_compare<GroupCompare, Group>
165 real_group_compare_type;
167 // The function object passed to the slot call iterator that will call
168 // the underlying slot function with its arguments bound
169 typedef BOOST_SIGNALS_NAMESPACE::detail::BOOST_SIGNALS_CALL_BOUND<R>
170 outer_bound_slot_caller;
171 typedef typename outer_bound_slot_caller::template
172 caller<BOOST_SIGNALS_TEMPLATE_ARGS
173 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
178 // Combiner's result type
179 typedef typename Combiner::result_type result_type;
182 typedef Combiner combiner_type;
185 typedef slot<slot_function_type> slot_type;
187 // Slot name type and comparison
188 typedef Group group_type;
189 typedef GroupCompare group_compare_type;
191 typedef typename BOOST_SIGNALS_NAMESPACE::detail::slot_call_iterator_generator<
193 slot_iterator>::type slot_call_iterator;
196 BOOST_SIGNALS_SIGNAL(const Combiner& c = Combiner(),
197 const GroupCompare& comp = GroupCompare()) :
198 BOOST_SIGNALS_NAMESPACE::detail::signal_base(real_group_compare_type(comp)),
203 // Connect a slot to this signal
204 BOOST_SIGNALS_NAMESPACE::connection connect(const slot_type&);
205 BOOST_SIGNALS_NAMESPACE::connection connect(const group_type&, const slot_type&);
207 // Disconnect a named slot
208 void disconnect(const group_type& group)
210 impl->disconnect(group);
214 result_type operator()(BOOST_SIGNALS_PARMS);
215 result_type operator()(BOOST_SIGNALS_PARMS) const;
223 BOOST_SIGNALS_TEMPLATE_PARMS
224 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
227 typename GroupCompare,
228 typename SlotFunction
230 BOOST_SIGNALS_NAMESPACE::connection
231 BOOST_SIGNALS_SIGNAL<
232 R, BOOST_SIGNALS_TEMPLATE_ARGS
233 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
234 Combiner, Group, GroupCompare, SlotFunction
235 >::connect(const slot_type& in_slot)
237 // If the slot has been disconnected, just return a disconnected
239 if (!in_slot.is_active()) {
240 return BOOST_SIGNALS_NAMESPACE::connection();
243 return impl->connect_slot(in_slot.get_slot_function(),
245 in_slot.get_bound_objects());
250 BOOST_SIGNALS_TEMPLATE_PARMS
251 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
254 typename GroupCompare,
255 typename SlotFunction
257 BOOST_SIGNALS_NAMESPACE::connection
258 BOOST_SIGNALS_SIGNAL<
259 R, BOOST_SIGNALS_TEMPLATE_ARGS
260 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
261 Combiner, Group, GroupCompare, SlotFunction
262 >::connect(const group_type& group,
263 const slot_type& in_slot)
265 return impl->connect_slot(in_slot.get_slot_function(),
267 in_slot.get_bound_objects());
272 BOOST_SIGNALS_TEMPLATE_PARMS
273 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
276 typename GroupCompare,
277 typename SlotFunction
279 typename BOOST_SIGNALS_SIGNAL<
280 R, BOOST_SIGNALS_TEMPLATE_ARGS
281 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
282 Combiner, Group, GroupCompare, SlotFunction>::result_type
283 BOOST_SIGNALS_SIGNAL<
284 R, BOOST_SIGNALS_TEMPLATE_ARGS
285 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
286 Combiner, Group, GroupCompare, SlotFunction
287 >::operator()(BOOST_SIGNALS_PARMS)
289 // Notify the slot handling code that we are making a call
290 BOOST_SIGNALS_NAMESPACE::detail::call_notification notification(this->impl);
292 // Construct a function object that will call the underlying slots
293 // with the given arguments.
294 #if BOOST_SIGNALS_NUM_ARGS == 0
295 BOOST_SIGNALS_ARGS_STRUCT_INST args;
297 BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
298 #endif // BOOST_SIGNALS_NUM_ARGS > 0
299 call_bound_slot f(&args);
301 // Let the combiner call the slots via a pair of input iterators
302 return combiner(BOOST_SIGNALS_NAMESPACE::detail::make_slot_call_iterator(
303 notification.impl->slots_.begin(), impl->slots_.end(), f),
304 BOOST_SIGNALS_NAMESPACE::detail::make_slot_call_iterator(
305 notification.impl->slots_.end(), impl->slots_.end(), f));
310 BOOST_SIGNALS_TEMPLATE_PARMS
311 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
314 typename GroupCompare,
315 typename SlotFunction
317 typename BOOST_SIGNALS_SIGNAL<
318 R, BOOST_SIGNALS_TEMPLATE_ARGS
319 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
320 Combiner, Group, GroupCompare, SlotFunction>::result_type
321 BOOST_SIGNALS_SIGNAL<
322 R, BOOST_SIGNALS_TEMPLATE_ARGS
323 BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
324 Combiner, Group, GroupCompare, SlotFunction
325 >::operator()(BOOST_SIGNALS_PARMS) const
327 // Notify the slot handling code that we are making a call
328 BOOST_SIGNALS_NAMESPACE::detail::call_notification notification(this->impl);
330 // Construct a function object that will call the underlying slots
331 // with the given arguments.
332 #if BOOST_SIGNALS_NUM_ARGS == 0
333 BOOST_SIGNALS_ARGS_STRUCT_INST args;
335 BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
336 #endif // BOOST_SIGNALS_NUM_ARGS > 0
338 call_bound_slot f(&args);
340 // Let the combiner call the slots via a pair of input iterators
341 return combiner(BOOST_SIGNALS_NAMESPACE::detail::make_slot_call_iterator(
342 notification.impl->slots_.begin(), impl->slots_.end(), f),
343 BOOST_SIGNALS_NAMESPACE::detail::make_slot_call_iterator(
344 notification.impl->slots_.end(), impl->slots_.end(), f));
348 #undef BOOST_SIGNAL_FUNCTION_N_HEADER
349 #undef BOOST_SIGNALS_ARGS_STRUCT_INST
350 #undef BOOST_SIGNALS_CALL_BOUND
351 #undef BOOST_SIGNALS_ARGS_STRUCT
352 #undef BOOST_SIGNALS_FUNCTION
353 #undef BOOST_SIGNALS_SIGNAL
354 #undef BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS