util: allow emitSignal with non-zero arguments
refs #2329
Change-Id: I7708878343f87bceff3c52c9266afcfd388e8683
diff --git a/src/util/signal-emit.hpp b/src/util/signal-emit.hpp
index 729d92a..17eacd0 100644
--- a/src/util/signal-emit.hpp
+++ b/src/util/signal-emit.hpp
@@ -51,16 +51,14 @@
* \note This macro should be used in 'protected' section so that it's accessible
* by derived classes.
* \note emit_signalName method is implementation detail.
- * Derived classes should use 'emit' macro.
+ * Derived classes should use 'emitSignal' macro.
* \note The name 'emit_signalName' is an intentional violation of code-style rule 2.5.
- * \note The DummyExtraArg is necessary so that 'emit' macro can be used for
- * both signals with zero arguments and signals with non-zero arguments.
* \note The method is declared as a template, so that the macro doesn't need argument types.
* But only argument types that are compatible with Signal declaration will work.
*/
#define DECLARE_SIGNAL_EMIT(signalName) \
template<typename ...TArgs> \
- void emit_##signalName(const TArgs&... args, const ::ndn::util::signal::DummyExtraArg&) \
+ void emit_##signalName(const TArgs&... args) \
{ \
signalName(args...); \
}
@@ -68,7 +66,7 @@
/** \brief (implementation detail) invokes emit_signalName method
* \note C99 requires at least one argument to be passed in __VA_ARGS__,
* thus a DummyExtraArg is expected at the end of __VA_ARGS__,
- * which will be accepted but ignored by emit_signalName method.
+ * which will be accepted but ignored by Signal::operator() overload.
*/
#define NDN_CXX_SIGNAL_EMIT(signalName, ...) \
emit_##signalName(__VA_ARGS__)
diff --git a/src/util/signal-signal.hpp b/src/util/signal-signal.hpp
index 444c702..e1c01df 100644
--- a/src/util/signal-signal.hpp
+++ b/src/util/signal-signal.hpp
@@ -29,6 +29,8 @@
namespace util {
namespace signal {
+class DummyExtraArg;
+
/** \brief provides a lightweight signal / event system
*
* To declare a signal:
@@ -76,6 +78,12 @@
void
operator()(const TArgs&...args);
+ /** \brief (implementation detail) emits a signal
+ * \note This overload is used by signal-emit.hpp.
+ */
+ void
+ operator()(const TArgs&...args, const DummyExtraArg&);
+
// make Owner a friend of Signal<Owner, ...> so that API for owner can be called
#if NDN_CXX_HAVE_CXX_FRIEND_TYPENAME
friend Owner;
@@ -208,6 +216,13 @@
m_isExecuting = false;
}
+template<typename Owner, typename ...TArgs>
+inline void
+Signal<Owner, TArgs...>::operator()(const TArgs&... args, const DummyExtraArg&)
+{
+ this->operator()(args...);
+}
+
} // namespace signal
// expose as ndn::util::Signal
diff --git a/tests/unit-tests/util/signal.cpp b/tests/unit-tests/util/signal.cpp
index afb4980..e0d70aa 100644
--- a/tests/unit-tests/util/signal.cpp
+++ b/tests/unit-tests/util/signal.cpp
@@ -68,6 +68,39 @@
BOOST_CHECK_EQUAL(hit2, 1);
}
+class SignalOwner1
+{
+public:
+ Signal<SignalOwner1, int> sig;
+
+protected:
+ DECLARE_SIGNAL_EMIT(sig)
+};
+
+class SignalEmitter1 : public SignalOwner1
+{
+public:
+ void
+ emitTestSignal()
+ {
+ this->emitSignal(sig, 8106);
+ }
+};
+
+BOOST_AUTO_TEST_CASE(OneArgument)
+{
+ SignalEmitter1 se;
+
+ int hit = 0;
+ se.sig.connect([&hit] (int a) {
+ ++hit;
+ BOOST_CHECK_EQUAL(a, 8106);
+ });
+ se.emitTestSignal();
+
+ BOOST_CHECK_EQUAL(hit, 1);
+}
+
BOOST_AUTO_TEST_CASE(TwoArguments)
{
Signal<std::remove_pointer<decltype(this)>::type, int, int> sig;