Skip to content

Commit 6e5eee0

Browse files
author
Kjell Ahlstedt
committed
Implement slot<R(Arg...)> with variadic template
* sigc++/functors/macros/slot.h.m4: Implement the function-style slot<R<Arg...)> with variadic template, as in libsigc++-3.0. The primary slot_call and the slot<T_return(T_arg...)> specialization are copied from libsigc++-3.0. A slot_call<T_functor, T_return> specialization is added. Bug #763393
1 parent d29b0ef commit 6e5eee0

File tree

1 file changed

+171
-69
lines changed

1 file changed

+171
-69
lines changed

sigc++/functors/macros/slot.h.m4

Lines changed: 171 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -266,74 +266,6 @@ public:
266266
}
267267
};
268268
269-
270-
/** Convenience wrapper for the numbered sigc::slot$1 template.
271-
* See the base class for useful methods.
272-
* This is the template specialization of the unnumbered sigc::slot
273-
* template for $1 argument(s), specialized for different numbers of arguments
274-
* This is possible because the template has default (nil) template types.
275-
dnl *
276-
dnl * @ingroup slot
277-
*
278-
* This specialization allow use of the sigc::slot<R(Args...)> syntax,
279-
*/
280-
template <LIST(class T_return, LOOP(class T_arg%1, $1))>
281-
class slot<T_return(LIST(LOOP(T_arg%1, $1)))>
282-
: public slot$1<LIST(T_return, LOOP(T_arg%1, $1))>
283-
{
284-
public:
285-
typedef slot$1<LIST(T_return, LOOP(T_arg%1, $1))> parent_type;
286-
287-
inline slot() {}
288-
289-
/** Constructs a slot from an arbitrary functor.
290-
* @param _A_func The desired functor the new slot should be assigned to.
291-
*/
292-
template <class T_functor>
293-
slot(const T_functor& _A_func)
294-
: parent_type(_A_func) {}
295-
296-
// Without static_cast parent_type(const T_functor& _A_func)
297-
// is called instead of the copy constructor.
298-
/** Constructs a slot, copying an existing one.
299-
* @param src The existing slot to copy.
300-
*/
301-
slot(const slot& src)
302-
: parent_type(static_cast<const parent_type&>(src)) {}
303-
304-
// Without static_cast parent_type(const T_functor& _A_func)
305-
// is called instead of the move constructor.
306-
/** Constructs a slot, moving an existing one.
307-
* If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
308-
* @param src The existing slot to move or copy.
309-
*/
310-
slot(slot&& src)
311-
: parent_type(std::move(static_cast<parent_type&>(src))) {}
312-
313-
/** Overrides this slot, making a copy from another slot.
314-
* @param src The slot from which to make a copy.
315-
* @return @p this.
316-
*/
317-
slot& operator=(const slot& src)
318-
{
319-
parent_type::operator=(src);
320-
return *this;
321-
}
322-
323-
/** Overrides this slot, making a move from another slot.
324-
* If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
325-
* @param src The slot from which to move or copy.
326-
* @return @p this.
327-
*/
328-
slot& operator=(slot&& src)
329-
{
330-
parent_type::operator=(std::move(src));
331-
return *this;
332-
}
333-
};
334-
335-
336-
337269
ifelse($1, $2,[dnl
338270
#ifndef DOXYGEN_SHOULD_SKIP_THIS
339271
//template specialization of visitor<>::do_visit_each<>(action, functor):
@@ -518,15 +450,185 @@ struct typed_slot_rep : public slot_rep
518450
}
519451
};
520452

521-
522453
FOR(0,CALL_SIZE,[[SLOT_CALL(%1)]])dnl
454+
455+
/** Abstracts functor execution.
456+
* call_it() invokes a functor of type @e T_functor with a list of
457+
* parameters whose types are given by the template arguments.
458+
* address() forms a function pointer from call_it().
459+
*
460+
* The following template arguments are used:
461+
* - @e T_functor The functor type.
462+
* - @e T_return The return type of call_it().
463+
* - @e T_arg Argument types used in the definition of call_it().
464+
*
465+
*/
466+
template<class T_functor, class T_return, class... T_arg>
467+
struct slot_call
468+
{
469+
/** Invokes a functor of type @p T_functor.
470+
* @param rep slot_rep object that holds a functor of type @p T_functor.
471+
* @param _A_a Arguments to be passed on to the functor.
472+
* @return The return values of the functor invocation.
473+
*/
474+
static T_return call_it(slot_rep* rep, type_trait_take_t<T_arg>... a_)
475+
{
476+
using typed_slot = typed_slot_rep<T_functor>;
477+
typed_slot *typed_rep = static_cast<typed_slot*>(rep);
478+
return (typed_rep->functor_).template operator()<type_trait_take_t<T_arg>...>
479+
(a_...);
480+
}
481+
482+
/** Forms a function pointer from call_it().
483+
* @return A function pointer formed from call_it().
484+
*/
485+
static hook address()
486+
{ return reinterpret_cast<hook>(&call_it); }
487+
};
488+
489+
/** Abstracts functor execution.
490+
* call_it() invokes a functor without parameters of type @e T_functor.
491+
* address() forms a function pointer from call_it().
492+
*
493+
* This is a specialization for functors without parameters.
494+
*
495+
* The following template arguments are used:
496+
* - @e T_functor The functor type.
497+
* - @e T_return The return type of call_it().
498+
*
499+
*/
500+
template<class T_functor, class T_return>
501+
struct slot_call<T_functor, T_return>
502+
{
503+
/** Invokes a functor of type @p T_functor.
504+
* @param rep slot_rep object that holds a functor of type @p T_functor.
505+
* @return The return values of the functor invocation.
506+
*/
507+
static T_return call_it(slot_rep* rep)
508+
{
509+
using typed_slot = typed_slot_rep<T_functor>;
510+
typed_slot *typed_rep = static_cast<typed_slot*>(rep);
511+
return (typed_rep->functor_)();
512+
}
513+
514+
/** Forms a function pointer from call_it().
515+
* @return A function pointer formed from call_it().
516+
*/
517+
static hook address()
518+
{ return reinterpret_cast<hook>(&call_it); }
519+
};
520+
523521
} /* namespace internal */
524522

525523

526524
FOR(0,CALL_SIZE,[[SLOT_N(%1,CALL_SIZE)]])
527525
SLOT(CALL_SIZE,CALL_SIZE)
528526
FOR(0,eval(CALL_SIZE-1),[[SLOT(%1,CALL_SIZE)]])
529527

528+
/** Converts an arbitrary functor to a unified type which is opaque.
529+
* sigc::slot itself is a functor or, to be more precise, a closure. It contains
530+
* a single, arbitrary functor (or closure) that is executed in operator()().
531+
*
532+
* The template arguments determine the function signature of operator()():
533+
* - @e T_return The return type of operator()().
534+
* - @e T_arg Argument types used in the definition of operator()().
535+
*
536+
* For instance, to declare a slot that returns void and takes two parameters
537+
* of bool and int:
538+
* @code
539+
* sigc::slot<void(bool, int)> some_slot;
540+
* @endcode
541+
*
542+
* Alternatively, you may use this syntax:
543+
* @code
544+
* sigc::slot<void, bool, int> some_slot;
545+
* @endcode
546+
*
547+
* To use, simply assign the desired functor to the slot. If the functor
548+
* is not compatible with the parameter list defined with the template
549+
* arguments then compiler errors are triggered. When called, the slot
550+
* will invoke the functor with minimal copies.
551+
* block() and unblock() can be used to block the functor's invocation
552+
* from operator()() temporarily.
553+
*
554+
* @ingroup slot
555+
*/
556+
template <class T_return, class... T_arg>
557+
class slot<T_return(T_arg...)>
558+
: public slot_base
559+
{
560+
public:
561+
using result_type = T_return;
562+
//TODO: using arg_type_ = type_trait_take_t<T_arg>;
563+
564+
#ifndef DOXYGEN_SHOULD_SKIP_THIS
565+
private:
566+
using rep_type = internal::slot_rep;
567+
public:
568+
using call_type = T_return (*)(rep_type*, type_trait_take_t<T_arg>...);
569+
#endif
570+
571+
/** Invoke the contained functor unless slot is in blocking state.
572+
* @param _A_a Arguments to be passed on to the functor.
573+
* @return The return value of the functor invocation.
574+
*/
575+
inline T_return operator()(type_trait_take_t<T_arg>... _A_a) const
576+
{
577+
if (!empty() && !blocked())
578+
return (reinterpret_cast<call_type>(slot_base::rep_->call_))(slot_base::rep_, _A_a...);
579+
return T_return();
580+
}
581+
582+
inline slot() {}
583+
584+
/** Constructs a slot from an arbitrary functor.
585+
* @param _A_func The desired functor the new slot should be assigned to.
586+
*/
587+
template <class T_functor>
588+
slot(const T_functor& _A_func)
589+
: slot_base(new internal::typed_slot_rep<T_functor>(_A_func))
590+
{
591+
//The slot_base:: is necessary to stop the HP-UX aCC compiler from being confused. murrayc.
592+
slot_base::rep_->call_ = internal::slot_call<T_functor, T_return, T_arg...>::address();
593+
}
594+
595+
/** Constructs a slot, copying an existing one.
596+
* @param src The existing slot to copy.
597+
*/
598+
slot(const slot& src)
599+
: slot_base(src)
600+
{}
601+
602+
/** Constructs a slot, moving an existing one.
603+
* If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
604+
* @param src The existing slot to move or copy.
605+
*/
606+
slot(slot&& src)
607+
: slot_base(std::move(src))
608+
{}
609+
610+
/** Overrides this slot, making a copy from another slot.
611+
* @param src The slot from which to make a copy.
612+
* @return @p this.
613+
*/
614+
slot& operator=(const slot& src)
615+
{
616+
slot_base::operator=(src);
617+
return *this;
618+
}
619+
620+
/** Overrides this slot, making a move from another slot.
621+
* If @p src is connected to a parent (e.g. a signal), it is copied, not moved.
622+
* @param src The slot from which to move or copy.
623+
* @return @p this.
624+
*/
625+
slot& operator=(slot&& src)
626+
{
627+
slot_base::operator=(std::move(src));
628+
return *this;
629+
}
630+
};
631+
530632
} /* namespace sigc */
531633

532634
#ifdef SIGC_NIL_HAS_BEEN_PUSHED

0 commit comments

Comments
 (0)