1 dnl Copyright 2002, The libsigc++ Development Team
3 dnl This library is free software; you can redistribute it and/or
4 dnl modify it under the terms of the GNU Lesser General Public
5 dnl License as published by the Free Software Foundation; either
6 dnl version 2.1 of the License, or (at your option) any later version.
8 dnl This library is distributed in the hope that it will be useful,
9 dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
10 dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 dnl Lesser General Public License for more details.
13 dnl You should have received a copy of the GNU Lesser General Public
14 dnl License along with this library; if not, write to the Free Software
15 dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 include(template.macros.m4)
22 /** Converts an arbitrary functor to a unified type which is opaque.
23 * sigc::slot itself is a functor or to be more precise a closure. It contains
24 * a single, arbitrary functor (or closure) that is executed in operator()().
26 * The template arguments determine the function signature of operator()():
27 * - @e T_return The return type of operator()().dnl
29 * - @e T_arg%1 Argument type used in the definition of operator()(). The default @p nil means no argument.])
31 * To use simply assign the desired functor to the slot. If the functor
32 * is not compatible with the parameter list defined with the template
33 * arguments compiler errors are triggered. When called the slot
34 * will invoke the functor with minimal copies.
35 * block() and unblock() can be used to block the functor's invocation
36 * from operator()() temporarily.
38 * You should use the more convenient unnumbered sigc::slot template.
42 template <LIST(class T_return, LOOP(class T_arg%1, $1))>
47 typedef T_return result_type;
48 FOR(1, $1,[ typedef _R_(T_arg%1) arg%1_type_;
51 #ifndef DOXYGEN_SHOULD_SKIP_THIS
53 typedef internal::slot_rep rep_type;
55 typedef T_return (*call_type)(LIST(rep_type*, LOOP(arg%1_type_, $1)));
58 /** Invoke the contained functor unless slot is in blocking state.dnl
60 * @param _A_a%1 Argument to be passed on to the functor.])
61 * @return The return value of the functor invocation.
63 inline T_return operator()(LOOP(arg%1_type_ _A_a%1, $1)) const
65 if (!empty() && !blocked())
66 return (sigc::internal::function_pointer_cast<call_type>(slot_base::rep_->call_))(LIST(slot_base::rep_, LOOP(_A_a%1, $1)));
72 /** Constructs a slot from an arbitrary functor.
73 * @param _A_func The desired functor the new slot should be assigned to.
75 template <class T_functor>
76 slot$1(const T_functor& _A_func)
77 : slot_base(new internal::typed_slot_rep<T_functor>(_A_func))
79 //The slot_base:: is necessary to stop the HP-UX aCC compiler from being confused. murrayc.
80 slot_base::rep_->call_ = internal::slot_call$1<LIST(T_functor, T_return, LOOP(T_arg%1, $1))>::address();
83 /** Constructs a slot, copying an existing one.
84 * @param src The existing slot to copy.
86 slot$1(const slot$1& src)
90 /** Constructs a slot, moving an existing one.
91 * If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
92 * @param src The existing slot to move or copy.
95 : slot_base(std::move(src))
98 /** Overrides this slot, making a copy from another slot.
99 * @param src The slot from which to make a copy.
102 slot$1& operator=(const slot$1& src)
104 slot_base::operator=(src);
108 /** Overrides this slot, making a move from another slot.
109 * If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
110 * @param src The slot from which to move or copy.
113 slot$1& operator=(slot$1&& src)
115 slot_base::operator=(std::move(src));
120 #ifndef DOXYGEN_SHOULD_SKIP_THIS
121 //template specialization of visitor<>::do_visit_each<>(action, functor):
122 /** Performs a functor on each of the targets of a functor.
123 * The function overloads for sigc::slot$1 are similar to the function
124 * overloads for sigc::slot. See the description of those overloads.
128 template <LIST(typename T_return, LOOP(typename T_arg%1, $1))>
129 struct visitor<slot$1<LIST(T_return, LOOP(T_arg%1, $1))>>
131 static void do_visit_each(const internal::limit_derived_target<trackable*, internal::slot_do_bind>& _A_action,
132 const slot$1<LIST(T_return, LOOP(T_arg%1, $1))>& _A_target)
134 if (_A_target.rep_ && _A_target.rep_->parent_ == nullptr)
135 _A_target.rep_->set_parent(_A_action.action_.rep_, &internal::slot_rep::notify);
138 static void do_visit_each(const internal::limit_derived_target<trackable*, internal::slot_do_unbind>& _A_action,
139 const slot$1<LIST(T_return, LOOP(T_arg%1, $1))>& _A_target)
141 if (_A_target.rep_ && _A_target.rep_->parent_ == _A_action.action_.rep_)
142 _A_target.rep_->set_parent(nullptr, nullptr);
145 template <typename T_action>
146 static void do_visit_each(const T_action& _A_action,
147 const slot$1<LIST(T_return, LOOP(T_arg%1, $1))>& _A_target)
149 _A_action(_A_target);
152 #endif // DOXYGEN_SHOULD_SKIP_THIS
157 // Because slot is opaque, visit_each() will not visit its internal members.
158 // Those members are not reachable by visit_each() after the slot has been
159 // constructed. But when a slot contains another slot, the outer slot will become
160 // the parent of the inner slot, with similar results. See the description of
161 // slot's specialization of the visitor struct.
162 /** Convenience wrapper for the numbered sigc::slot# templates.
163 * Slots convert arbitrary functors to unified types which are opaque.
164 * sigc::slot itself is a functor or to be more precise a closure. It contains
165 * a single, arbitrary functor (or closure) that is executed in operator()().
167 * The template arguments determine the function signature of operator()():
168 * - @e T_return The return type of operator()().dnl
170 * - @e T_arg%1 Argument type used in the definition of operator()(). The default @p nil means no argument.])
172 * To use, simply assign the desired functor to the slot. If the functor
173 * is not compatible with the parameter list defined with the template
174 * arguments, compiler errors are triggered. When called, the slot
175 * will invoke the functor with minimal copies.
176 * block() and unblock() can be used to temporarily block the functor's
177 * invocation from operator()().
182 * sigc::slot<void, int> s = sigc::ptr_fun(&foo);
186 * sigc::slot<> is similar to std::function<>. If you're going to assign the
187 * resulting functor to a sigc::slot or connect it to a sigc::signal, it's better
188 * not to use std::function. It would become an unnecessary extra wrapper.
190 * @deprecated Please use the syntax similar to that used by std::function<>:
192 * sigc::slot<void(bool, int)> some_slot;
197 template <LIST(class T_return, LOOP(class T_arg%1 = nil, $1))>
200 /** Convenience wrapper for the numbered sigc::slot$1 template.
201 * See the base class for useful methods.
202 * This is the template specialization of the unnumbered sigc::slot
203 * template for $1 argument(s), specialized for different numbers of arguments
204 * This is possible because the template has default (nil) template types.
206 * @deprecated Please use the syntax similar to that used by std::function<>:
208 * sigc::slot<void(bool, int)> some_slot;
214 template <LIST(class T_return, LOOP(class T_arg%1, $1))>
215 class slot <LIST(T_return, LIST(LOOP(T_arg%1, $1), LOOP(nil, CALL_SIZE - $1)))>])
216 : public slot$1<LIST(T_return, LOOP(T_arg%1, $1))>
219 typedef slot$1<LIST(T_return, LOOP(T_arg%1, $1))> parent_type;
223 /** Constructs a slot from an arbitrary functor.
224 * @param _A_func The desired functor the new slot should be assigned to.
226 template <class T_functor>
227 slot(const T_functor& _A_func)
228 : parent_type(_A_func) {}
230 // Without static_cast parent_type(const T_functor& _A_func)
231 // is called instead of the copy constructor.
232 /** Constructs a slot, copying an existing one.
233 * @param src The existing slot to copy.
235 slot(const slot& src)
236 : parent_type(static_cast<const parent_type&>(src)) {}
238 // Without static_cast parent_type(const T_functor& _A_func)
239 // is called instead of the move constructor.
240 /** Constructs a slot, moving an existing one.
241 * If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
242 * @param src The existing slot to move or copy.
245 : parent_type(std::move(static_cast<parent_type&>(src))) {}
247 /** Overrides this slot, making a copy from another slot.
248 * @param src The slot from which to make a copy.
251 slot& operator=(const slot& src)
253 parent_type::operator=(src);
257 /** Overrides this slot, making a move from another slot.
258 * If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
259 * @param src The slot from which to move or copy.
262 slot& operator=(slot&& src)
264 parent_type::operator=(std::move(src));
270 #ifndef DOXYGEN_SHOULD_SKIP_THIS
271 //template specialization of visitor<>::do_visit_each<>(action, functor):
272 /** Performs a functor on each of the targets of a functor.
274 * There are three function overloads for sigc::slot.
276 * The first two overloads are very specialized. They handle the (probably unusual)
277 * case when the functor, stored in a slot, contains a slot. They are invoked from
278 * the constructor, destructor or destroy() method of typed_slot_rep.
279 * The first overload, called from the constructor of the outer slot, sets
280 * the outer slot as the parent of the inner slot. The second overload, called from
281 * the destructor or destroy() of the outer slot, unsets the parent of the inner slot.
282 * When an object referenced from the inner slot is deleted, the inner slot calls
283 * its slot_rep::disconnect(), which calls the outer slot's slot_rep::notify().
284 * The outer slot is informed just as if one of its directly referenced objects
285 * had been deleted. Result: The outer slot is disconnected from its parent,
286 * if any (for instance a sigc::signal).
287 * See https://bugzilla.gnome.org/show_bug.cgi?id=755003
289 * The third overload is identical to do_visit_each() in visitor's primary template.
293 template <LIST(typename T_return, LOOP(typename T_arg%1, $1))>
294 struct visitor<slot<LIST(T_return, LOOP(T_arg%1, $1))>>
296 static void do_visit_each(const internal::limit_derived_target<trackable*, internal::slot_do_bind>& _A_action,
297 const slot<LIST(T_return, LOOP(T_arg%1, $1))>& _A_target)
299 if (_A_target.rep_ && _A_target.rep_->parent_ == nullptr)
300 _A_target.rep_->set_parent(_A_action.action_.rep_, &internal::slot_rep::notify);
303 static void do_visit_each(const internal::limit_derived_target<trackable*, internal::slot_do_unbind>& _A_action,
304 const slot<LIST(T_return, LOOP(T_arg%1, $1))>& _A_target)
306 if (_A_target.rep_ && _A_target.rep_->parent_ == _A_action.action_.rep_)
307 _A_target.rep_->set_parent(nullptr, nullptr);
310 template <typename T_action>
311 static void do_visit_each(const T_action& _A_action,
312 const slot<LIST(T_return, LOOP(T_arg%1, $1))>& _A_target)
314 _A_action(_A_target);
317 #endif // DOXYGEN_SHOULD_SKIP_THIS
320 define([SLOT_CALL],[dnl
321 /** Abstracts functor execution.
322 * call_it() invokes a functor of type @e T_functor with a list of
323 * parameters whose types are given by the template arguments.
324 * address() forms a function pointer from call_it().
326 * The following template arguments are used:
327 * - @e T_functor The functor type.
328 * - @e T_return The return type of call_it().dnl
330 * - @e T_arg%1 Argument type used in the definition of call_it().])
333 template<LIST(class T_functor, class T_return, LOOP(class T_arg%1, $1))>
336 /** Invokes a functor of type @p T_functor.
337 * @param rep slot_rep object that holds a functor of type @p T_functor.dnl
339 * @param _A_a%1 Argument to be passed on to the functor.])
340 * @return The return values of the functor invocation.
342 static T_return call_it(LIST(slot_rep* rep, LOOP(_R_(T_arg%1) a_%1, $1)))
344 typedef typed_slot_rep<T_functor> typed_slot;
345 typed_slot *typed_rep = static_cast<typed_slot*>(rep);dnl
347 return (typed_rep->functor_)();
349 return (typed_rep->functor_).SIGC_WORKAROUND_OPERATOR_PARENTHESES<LOOP([_R_(T_arg%1)],$1)>
354 /** Forms a function pointer from call_it().
355 * @return A function pointer formed from call_it().
357 static hook address()
358 { return sigc::internal::function_pointer_cast<hook>(&call_it); }
364 _FIREWALL([FUNCTORS_SLOT])
365 #include <sigc++/trackable.h>
366 #include <sigc++/visit_each.h>
367 #include <sigc++/adaptors/adaptor_trait.h>
368 #include <sigc++/functors/slot_base.h>
370 //TODO: See comment in functor_trait.h.
371 #if defined(nil) && defined(SIGC_PRAGMA_PUSH_POP_MACRO)
372 #define SIGC_NIL_HAS_BEEN_PUSHED 1
373 #pragma push_macro("nil")
381 // Conversion between different types of function pointers with
382 // reinterpret_cast can make gcc8 print a warning.
383 // https://github.com/libsigcplusplus/libsigcplusplus/issues/1
384 // https://github.com/libsigcplusplus/libsigcplusplus/issues/8
385 /** Returns the supplied function pointer, cast to a pointer to another function type.
387 * When a single reinterpret_cast between function pointer types causes a
388 * compiler warning or error, this function may work.
390 * Qualify calls with namespace names: sigc::internal::function_pointer_cast<>().
391 * If you don't, indirect calls from another library that also contains a
392 * function_pointer_cast<>() (perhaps glibmm), can be ambiguous due to ADL
393 * (argument-dependent lookup).
395 template <typename T_out, typename T_in>
396 inline T_out function_pointer_cast(T_in in)
398 // The double reinterpret_cast suppresses a warning from gcc8 with the
399 // -Wcast-function-type option.
400 return reinterpret_cast<T_out>(reinterpret_cast<void (*)()>(in));
403 /** A typed slot_rep.
404 * A typed slot_rep holds a functor that can be invoked from
405 * slot::operator()(). visit_each() is used to visit the functor's
406 * targets that inherit trackable recursively and register the
407 * notification callback. Consequently the slot_rep object will be
408 * notified when some referred object is destroyed or overwritten.
410 template <class T_functor>
411 struct typed_slot_rep : public slot_rep
413 typedef typed_slot_rep<T_functor> self;
415 /* Use an adaptor type so that arguments can be passed as const references
416 * through explicit template instantiation from slot_call#::call_it() */
417 typedef typename adaptor_trait<T_functor>::adaptor_type adaptor_type;
419 /** The functor contained by this slot_rep object. */
420 adaptor_type functor_;
422 /** Constructs an invalid typed slot_rep object.
423 * The notification callback is registered using visit_each().
424 * @param functor The functor contained by the new slot_rep object.
426 inline typed_slot_rep(const T_functor& functor)
427 : slot_rep(nullptr, &destroy, &dup), functor_(functor)
428 { sigc::visit_each_type<trackable*>(slot_do_bind(this), functor_); }
430 inline typed_slot_rep(const typed_slot_rep& cl)
431 : slot_rep(cl.call_, &destroy, &dup), functor_(cl.functor_)
432 { sigc::visit_each_type<trackable*>(slot_do_bind(this), functor_); }
434 typed_slot_rep& operator=(const typed_slot_rep& src) = delete;
436 typed_slot_rep(typed_slot_rep&& src) = delete;
437 typed_slot_rep& operator=(typed_slot_rep&& src) = delete;
439 inline ~typed_slot_rep()
443 sigc::visit_each_type<trackable*>(slot_do_unbind(this), functor_);
446 /** Detaches the stored functor from the other referred trackables and destroys it.
447 * This does not destroy the base slot_rep object.
449 static void* destroy(void* data)
451 self* self_ = static_cast<self*>(reinterpret_cast<slot_rep*>(data));
452 self_->call_ = nullptr;
453 self_->destroy_ = nullptr;
454 sigc::visit_each_type<trackable*>(slot_do_unbind(self_), self_->functor_);
455 self_->functor_.~adaptor_type();
456 /* don't call disconnect() here: destroy() is either called
457 * a) from the parent itself (in which case disconnect() leads to a segfault) or
458 * b) from a parentless slot (in which case disconnect() does nothing)
463 /** Makes a deep copy of the slot_rep object.
464 * Deep copy means that the notification callback of the new
465 * slot_rep object is registered in the referred trackables.
466 * @return A deep copy of the slot_rep object.
468 static void* dup(void* data)
470 slot_rep* a_rep = reinterpret_cast<slot_rep*>(data);
471 return static_cast<slot_rep*>(new self(*static_cast<self*>(a_rep)));
475 FOR(0,CALL_SIZE,[[SLOT_CALL(%1)]])dnl
477 /** Abstracts functor execution.
478 * call_it() invokes a functor of type @e T_functor with a list of
479 * parameters whose types are given by the template arguments.
480 * address() forms a function pointer from call_it().
482 * The following template arguments are used:
483 * - @e T_functor The functor type.
484 * - @e T_return The return type of call_it().
485 * - @e T_arg Argument types used in the definition of call_it().
488 template<class T_functor, class T_return, class... T_arg>
491 /** Invokes a functor of type @p T_functor.
492 * @param rep slot_rep object that holds a functor of type @p T_functor.
493 * @param _A_a Arguments to be passed on to the functor.
494 * @return The return values of the functor invocation.
496 static T_return call_it(slot_rep* rep, type_trait_take_t<T_arg>... a_)
498 using typed_slot = typed_slot_rep<T_functor>;
499 typed_slot *typed_rep = static_cast<typed_slot*>(rep);
500 return (typed_rep->functor_).SIGC_WORKAROUND_OPERATOR_PARENTHESES<type_trait_take_t<T_arg>...>
504 /** Forms a function pointer from call_it().
505 * @return A function pointer formed from call_it().
507 static hook address()
508 { return sigc::internal::function_pointer_cast<hook>(&call_it); }
511 /** Abstracts functor execution.
512 * call_it() invokes a functor without parameters of type @e T_functor.
513 * address() forms a function pointer from call_it().
515 * This is a specialization for functors without parameters.
517 * The following template arguments are used:
518 * - @e T_functor The functor type.
519 * - @e T_return The return type of call_it().
522 template<class T_functor, class T_return>
523 struct slot_call<T_functor, T_return>
525 /** Invokes a functor of type @p T_functor.
526 * @param rep slot_rep object that holds a functor of type @p T_functor.
527 * @return The return values of the functor invocation.
529 static T_return call_it(slot_rep* rep)
531 using typed_slot = typed_slot_rep<T_functor>;
532 typed_slot *typed_rep = static_cast<typed_slot*>(rep);
533 return (typed_rep->functor_)();
536 /** Forms a function pointer from call_it().
537 * @return A function pointer formed from call_it().
539 static hook address()
540 { return sigc::internal::function_pointer_cast<hook>(&call_it); }
543 } /* namespace internal */
546 FOR(0,CALL_SIZE,[[SLOT_N(%1,CALL_SIZE)]])
547 SLOT(CALL_SIZE,CALL_SIZE)
548 FOR(0,eval(CALL_SIZE-1),[[SLOT(%1,CALL_SIZE)]])
550 /** Converts an arbitrary functor to a unified type which is opaque.
551 * sigc::slot itself is a functor or, to be more precise, a closure. It contains
552 * a single, arbitrary functor (or closure) that is executed in operator()().
554 * The template arguments determine the function signature of operator()():
555 * - @e T_return The return type of operator()().
556 * - @e T_arg Argument types used in the definition of operator()().
558 * For instance, to declare a slot that returns void and takes two parameters
561 * sigc::slot<void(bool, int)> some_slot;
564 * Alternatively, you may use this syntax:
566 * sigc::slot<void, bool, int> some_slot;
569 * To use, simply assign the desired functor to the slot. If the functor
570 * is not compatible with the parameter list defined with the template
571 * arguments then compiler errors are triggered. When called, the slot
572 * will invoke the functor with minimal copies.
573 * block() and unblock() can be used to block the functor's invocation
574 * from operator()() temporarily.
578 template <class T_return, class... T_arg>
579 class slot<T_return(T_arg...)>
583 using result_type = T_return;
584 //TODO: using arg_type_ = type_trait_take_t<T_arg>;
586 #ifndef DOXYGEN_SHOULD_SKIP_THIS
588 using rep_type = internal::slot_rep;
590 using call_type = T_return (*)(rep_type*, type_trait_take_t<T_arg>...);
593 /** Invoke the contained functor unless slot is in blocking state.
594 * @param _A_a Arguments to be passed on to the functor.
595 * @return The return value of the functor invocation.
597 inline T_return operator()(type_trait_take_t<T_arg>... _A_a) const
599 if (!empty() && !blocked())
600 return (sigc::internal::function_pointer_cast<call_type>(slot_base::rep_->call_))(slot_base::rep_, _A_a...);
606 /** Constructs a slot from an arbitrary functor.
607 * @param _A_func The desired functor the new slot should be assigned to.
609 template <class T_functor>
610 slot(const T_functor& _A_func)
611 : slot_base(new internal::typed_slot_rep<T_functor>(_A_func))
613 //The slot_base:: is necessary to stop the HP-UX aCC compiler from being confused. murrayc.
614 slot_base::rep_->call_ = internal::slot_call<T_functor, T_return, T_arg...>::address();
617 /** Constructs a slot, copying an existing one.
618 * @param src The existing slot to copy.
620 slot(const slot& src)
624 /** Constructs a slot, moving an existing one.
625 * If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
626 * @param src The existing slot to move or copy.
629 : slot_base(std::move(src))
632 /** Overrides this slot, making a copy from another slot.
633 * @param src The slot from which to make a copy.
636 slot& operator=(const slot& src)
638 slot_base::operator=(src);
642 /** Overrides this slot, making a move from another slot.
643 * If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
644 * @param src The slot from which to move or copy.
647 slot& operator=(slot&& src)
649 slot_base::operator=(std::move(src));
654 } /* namespace sigc */
656 #ifdef SIGC_NIL_HAS_BEEN_PUSHED
657 #undef SIGC_NIL_HAS_BEEN_PUSHED
658 #pragma pop_macro("nil")