From 7bca844581a38fbf46f8a3761cbd5e31bd9005d6 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Thu, 19 May 2011 12:32:42 +0200 Subject: Prepare the Slot classes to be used independently of Signals Added some polish around them and, to mark this special occasion, moved them out of the SigImpl namespace. PS: This partially reverts commit 0775350fee345e37fb59835dda4d85664346b606, since I had to reintroduce ReturnType template parameter, because it will be used in other places. But Signal classes remain without the ReturnType, because I still cannot imagine how would it be used. --- src/FbTk/Signal.hh | 91 ++++++++++++++++++++++++++++++++++-------------------- src/FbTk/Slot.hh | 90 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 117 insertions(+), 64 deletions(-) diff --git a/src/FbTk/Signal.hh b/src/FbTk/Signal.hh index 0148a17..31fd840 100644 --- a/src/FbTk/Signal.hh +++ b/src/FbTk/Signal.hh @@ -22,6 +22,7 @@ #ifndef FBTK_SIGNAL_HH #define FBTK_SIGNAL_HH +#include "RefCount.hh" #include "Slot.hh" #include #include @@ -120,66 +121,90 @@ private: unsigned m_emitting; }; -template -class SignalTemplate: public SignalHolder { -public: - template - SlotID connect(const Functor& functor) { - return SignalHolder::connect(SlotPtr( new Slot(functor) )); - } +} // namespace SigImpl -protected: - void emit_(Arg1 arg1, Arg2 arg2, Arg3 arg3) { + +/// Specialization for three arguments. +template +class Signal: public SigImpl::SignalHolder { +public: + void emit(Arg1 arg1, Arg2 arg2, Arg3 arg3) { begin_emitting(); for ( Iterator it = begin(); it != end(); ++it ) { if(*it) - static_cast &>(**it)(arg1, arg2, arg3); + static_cast &>(**it)(arg1, arg2, arg3); } end_emitting(); } -}; - -} // namespace SigImpl - -/// Base template for three arguments. -template -class Signal: public SigImpl::SignalTemplate { -public: - void emit(Arg1 arg1, Arg2 arg2, Arg3 arg3) - { SigImpl::SignalTemplate::emit_(arg1, arg2, arg3); } + template + SlotID connect(const Functor& functor) { + return SignalHolder::connect(SlotPtr( + new SlotImpl(functor) + )); + } }; /// Specialization for two arguments. template -class Signal: - public SigImpl::SignalTemplate { +class Signal: public SigImpl::SignalHolder { public: void emit(Arg1 arg1, Arg2 arg2) { - SigImpl::SignalTemplate:: - emit_(arg1, arg2, SigImpl::EmptyArg()); + begin_emitting(); + for ( Iterator it = begin(); it != end(); ++it ) { + if(*it) + static_cast &>(**it)(arg1, arg2); + } + end_emitting(); + } + + template + SlotID connect(const Functor& functor) { + return SignalHolder::connect(SlotPtr( + new SlotImpl(functor) + )); } }; /// Specialization for one argument. template -class Signal: - public SigImpl::SignalTemplate { +class Signal: public SigImpl::SignalHolder { public: - void emit(Arg1 arg1) { - SigImpl::SignalTemplate - ::emit_(arg1, SigImpl::EmptyArg(), SigImpl::EmptyArg()); + void emit(Arg1 arg) { + begin_emitting(); + for ( Iterator it = begin(); it != end(); ++it ) { + if(*it) + static_cast &>(**it)(arg); + } + end_emitting(); + } + + template + SlotID connect(const Functor& functor) { + return SignalHolder::connect(SlotPtr( + new SlotImpl(functor) + )); } }; /// Specialization for no arguments. template <> -class Signal: - public SigImpl::SignalTemplate { +class Signal: public SigImpl::SignalHolder { public: void emit() { - SigImpl::SignalTemplate - ::emit_(SigImpl::EmptyArg(), SigImpl::EmptyArg(), SigImpl::EmptyArg()); + begin_emitting(); + for ( Iterator it = begin(); it != end(); ++it ) { + if(*it) + static_cast &>(**it)(); + } + end_emitting(); + } + + template + SlotID connect(const Functor& functor) { + return SignalHolder::connect(SlotPtr( + new SlotImpl(functor) + )); } }; diff --git a/src/FbTk/Slot.hh b/src/FbTk/Slot.hh index ea7ee2f..71bf6ab 100644 --- a/src/FbTk/Slot.hh +++ b/src/FbTk/Slot.hh @@ -22,7 +22,7 @@ #ifndef FBTK_SLOT_HH #define FBTK_SLOT_HH -#include "RefCount.hh" +#include "NotCopyable.hh" namespace FbTk { @@ -31,71 +31,99 @@ namespace SigImpl { struct EmptyArg {}; -class SlotBase { +/** A base class for all slots. It's purpose is to provide a virtual destructor and to enable the + * Signal class to hold a pointer to a generic slot. + */ +class SlotBase: private FbTk::NotCopyable { public: virtual ~SlotBase() {} }; -template -class SlotTemplate: public SlotBase { +} // namespace SigImpl + +/** Declares a pure virtual function call operator with a specific number of arguments (depending + * on the template specialization). This allows us to "call" any functor in an opaque way. + */ +template +class Slot: public SigImpl::SlotBase { +public: + virtual ReturnType operator()(Arg1, Arg2, Arg3) = 0; +}; + +/// Specialization for two arguments +template +class Slot: public SigImpl::SlotBase { +public: + virtual ReturnType operator()(Arg1, Arg2) = 0; +}; + +/// Specialization for one argument +template +class Slot: public SigImpl::SlotBase { +public: + virtual ReturnType operator()(Arg1) = 0; +}; + +/// Specialization for no arguments +template +class Slot: public SigImpl::SlotBase { public: - virtual void operator()(Arg1, Arg2, Arg3) = 0; + virtual ReturnType operator()() = 0; }; -template -class Slot: public SlotTemplate { +/** A class which knows how to call a specific functor. It inherits from Slot and implemetents + * the function call operator + */ +template +class SlotImpl: public Slot { public: - virtual void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3) - { m_functor(arg1, arg2, arg3); } + virtual ReturnType operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3) + { return m_functor(arg1, arg2, arg3); } - Slot(Functor functor) : m_functor(functor) {} + SlotImpl(Functor functor) : m_functor(functor) {} private: Functor m_functor; }; -// specialization for two arguments -template -class Slot: public SlotTemplate { +/// Specialization for two arguments +template +class SlotImpl: public Slot { public: - virtual void operator()(Arg1 arg1, Arg2 arg2, EmptyArg) - { m_functor(arg1, arg2); } + virtual ReturnType operator()(Arg1 arg1, Arg2 arg2) { return m_functor(arg1, arg2); } - Slot(Functor functor) : m_functor(functor) {} + SlotImpl(Functor functor) : m_functor(functor) {} private: Functor m_functor; }; -// specialization for one argument -template -class Slot: public SlotTemplate { +/// Specialization for one argument +template +class SlotImpl: public Slot { public: - virtual void operator()(Arg1 arg1, EmptyArg, EmptyArg) - { m_functor(arg1); } + virtual ReturnType operator()(Arg1 arg1) { return m_functor(arg1); } - Slot(Functor functor) : m_functor(functor) {} + SlotImpl(Functor functor) : m_functor(functor) {} private: Functor m_functor; }; -// specialization for no arguments -template -class Slot: public SlotTemplate { +/// Specialization for no arguments +template +class SlotImpl: public Slot { public: - virtual void operator()(EmptyArg, EmptyArg, EmptyArg) - { m_functor(); } + virtual ReturnType operator()() { return m_functor(); } - Slot(Functor functor) : m_functor(functor) {} + SlotImpl(Functor functor) : m_functor(functor) {} private: Functor m_functor; }; -} // namespace SigImpl - } // namespace FbTk - #endif // FBTK_SLOT_H -- cgit v0.11.2