summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMurray Cumming <murrayc@murrayc.com>2016-01-14 12:13:02 +0100
committerMurray Cumming <murrayc@murrayc.com>2016-03-02 11:52:29 +0100
commite91fd7c3b0d6319c6f0dcd3f6069ecee5d66f7af (patch)
tree5c3c690f053fb8312e80f10e1adef3874d730154
parent8f6f7d298e1910183473b59df32d5dd45c5bb359 (diff)
downloadsigc++-e91fd7c3b0d6319c6f0dcd3f6069ecee5d66f7af.tar.gz
signal.h.m4: signal_emit1/2/3/etc: Make this variadic.
Though we still have the separate generated signal_emit1/2/3, etc. This is the first time that we need to use a tuple, and then std::index_sequence(), to call another method with the stored (in a tuple) parameter pack.
-rw-r--r--sigc++/macros/signal.h.m4132
1 files changed, 62 insertions, 70 deletions
diff --git a/sigc++/macros/signal.h.m4 b/sigc++/macros/signal.h.m4
index 7842e84..05ffa94 100644
--- a/sigc++/macros/signal.h.m4
+++ b/sigc++/macros/signal.h.m4
@@ -25,44 +25,39 @@ define([SIGNAL_EMIT_N],[dnl
* emission when no accumulator is used, for example when the template
* argument @e T_accumulator is @p nil.
*/
-template <LIST(class T_return, class T_accumulator, LOOP(class T_arg%1, $1))>
+template <class T_return, class T_accumulator, class... T_arg>
struct signal_emit$1
{
- typedef signal_emit$1<LIST(T_return, T_accumulator, LOOP(T_arg%1, $1))> self_type;
+ typedef signal_emit$1<T_return, T_accumulator, T_arg...> self_type;
typedef typename T_accumulator::result_type result_type;
- typedef slot<LIST(T_return, LOOP(T_arg%1, $1))> slot_type;
+ typedef slot<T_return, T_arg...> slot_type;
typedef internal::slot_iterator_buf<self_type, T_return> slot_iterator_buf_type;
typedef internal::slot_reverse_iterator_buf<self_type, T_return> slot_reverse_iterator_buf_type;
typedef signal_impl::const_iterator_type iterator_type;
-ifelse($1,0,,[dnl
/** Instantiates the class.
* The parameters are stored in member variables. operator()() passes
* the values on to some slot.
*/
-])dnl
- signal_emit$1(LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)) ifelse($1,0,,[
- : LOOP(_A_a%1_(_A_a%1), $1)]) {}
+ signal_emit$1(type_trait_take_t<T_arg>... _A_a)
+ : _A_a_(_A_a...) {}
-ifelse($1,0,[dnl
- /** Invokes a slot.],[
- /** Invokes a slot using the buffered parameter values.])
+ /** Invokes a slot using the buffered parameter values.
* @param _A_slot Some slot to invoke.
* @return The slot's return value.
*/
T_return operator()(const slot_type& _A_slot) const
- { return (reinterpret_cast<typename slot_type::call_type>(_A_slot.rep_->call_))(LIST(_A_slot.rep_, LOOP(_A_a%1_, $1))); }
-dnl T_return operator()(const slot_type& _A_slot) const
-dnl { return _A_slot(LOOP(_A_a%1_, $1)); }
+ {
+ const auto seq = std::make_index_sequence<std::tuple_size<decltype(_A_a_)>::value>();
+ return call_call_type_operator_parentheses_with_tuple(_A_slot, _A_a_, seq);
+ }
- /** Executes a list of slots using an accumulator of type @e T_accumulator.dnl
-ifelse($1,0,,[
- * The arguments are buffered in a temporary instance of signal_emit$1.])
-FOR(1, $1,[
- * @param _A_a%1 Argument to be passed on to the slots.])
+ /** Executes a list of slots using an accumulator of type @e T_accumulator.
+ * The arguments are buffered in a temporary instance of signal_emit$1.
+ * @param _A_a Arguments to be passed on to the slots.
* @return The accumulated return values of the slot invocations as processed by the accumulator.
*/
- static result_type emit(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
+ static result_type emit(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
{
T_accumulator accumulator;
@@ -72,19 +67,17 @@ FOR(1, $1,[
signal_exec exec(impl);
temp_slot_list slots(impl->slots_);
- self_type self ifelse($1,0,,[(LOOP(_A_a%1, $1))]);
+ self_type self(_A_a...);
return accumulator(slot_iterator_buf_type(slots.begin(), &self),
slot_iterator_buf_type(slots.end(), &self));
}
/** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.dnl
-ifelse($1,0,,[
- * The arguments are buffered in a temporary instance of signal_emit$1.])
-FOR(1, $1,[
- * @param _A_a%1 Argument to be passed on to the slots.])
+ * The arguments are buffered in a temporary instance of signal_emit$1.
+ * @param _A_a Arguments to be passed on to the slots.
* @return The accumulated return values of the slot invocations as processed by the accumulator.
*/
- static result_type emit_reverse(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
+ static result_type emit_reverse(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
{
T_accumulator accumulator;
@@ -94,39 +87,47 @@ FOR(1, $1,[
signal_exec exec(impl);
temp_slot_list slots(impl->slots_);
- self_type self ifelse($1,0,,[(LOOP(_A_a%1, $1))]);
+ self_type self(_A_a...);
return accumulator(slot_reverse_iterator_buf_type(slots.end(), &self),
slot_reverse_iterator_buf_type(slots.begin(), &self));
}
-dnl
- FOR(1, $1,[
- type_trait_take_t<T_arg%1> _A_a%1_;])
+
+ std::tuple<type_trait_take_t<T_arg>...> _A_a_;
+
+private:
+ //TODO: Replace this with std::experimental::apply() if that becomes standard
+ //C++, or add our own implementation, to avoid code duplication.
+ template<std::size_t... Is>
+ decltype(auto)
+ call_call_type_operator_parentheses_with_tuple(const slot_type& _A_slot, const std::tuple<T_arg...>& tuple,
+ std::index_sequence<Is...>) const
+ {
+ return (_A_slot)(std::get<Is>(tuple)...);
+ }
};
/** Abstracts signal emission.
* This template specialization implements an optimized emit()
* function for the case that no accumulator is used.
*/
-template <LIST(class T_return, LOOP(class T_arg%1, $1))>
-struct signal_emit$1<LIST(T_return, nil, LOOP(T_arg%1, $1))>
+template <class T_return, class... T_arg>
+struct signal_emit$1<T_return, nil, T_arg...>
{
- typedef signal_emit$1<LIST(T_return, nil, LOOP(T_arg%1, $1)) > self_type;
+ typedef signal_emit$1<T_return, nil, T_arg...> self_type;
typedef T_return result_type;
- typedef slot<LIST(T_return, LOOP(T_arg%1, $1))> slot_type;
+ typedef slot<T_return, T_arg...> slot_type;
typedef signal_impl::const_iterator_type iterator_type;
typedef typename slot_type::call_type call_type;
- /** Executes a list of slots using an accumulator of type @e T_accumulator.dnl
-ifelse($1,0,,[
- * The arguments are passed directly on to the slots.])
+ /** Executes a list of slots.
+ * The arguments are passed directly on to the slots.
* The return value of the last slot invoked is returned.
* @param first An iterator pointing to the first slot in the list.
* @param last An iterator pointing to the last slot in the list.dnl
-FOR(1, $1,[
- * @param _A_a%1 Argument to be passed on to the slots.])
+ * @param _A_a Arguments to be passed on to the slots.
* @return The return value of the last slot invoked.
*/
- static result_type emit(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
+ static result_type emit(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
{
if (!impl || impl->slots_.empty())
return T_return();
@@ -145,29 +146,24 @@ FOR(1, $1,[
if (it == slots.end())
return T_return(); // note that 'T_return r_();' doesn't work => define 'r_' after this line and initialize as follows:
- r_ = (reinterpret_cast<call_type>(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1)));
+ r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
for (++it; it != slots.end(); ++it)
{
if (it->empty() || it->blocked())
continue;
- r_ = (reinterpret_cast<call_type>(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1)));
+ r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
}
}
return r_;
}
- /** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.dnl
-ifelse($1,0,,[
- * The arguments are passed directly on to the slots.])
- * The return value of the last slot invoked is returned.
- * @param first An iterator pointing to the first slot in the list.
- * @param last An iterator pointing to the last slot in the list.dnl
-FOR(1, $1,[
- * @param _A_a%1 Argument to be passed on to the slots.])
+ /** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.
+ * The arguments are passed directly on to the slots.
+ * @param _A_a%1 Argument to be passed on to the slots.
* @return The return value of the last slot invoked.
*/
- static result_type emit_reverse(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
+ static result_type emit_reverse(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
{
if (!impl || impl->slots_.empty())
return T_return();
@@ -193,12 +189,12 @@ FOR(1, $1,[
if (it == reverse_iterator_type(slots.begin()))
return T_return(); // note that 'T_return r_();' doesn't work => define 'r_' after this line and initialize as follows:
- r_ = (reinterpret_cast<call_type>(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1)));
+ r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
for (++it; it != reverse_iterator_type(slots.begin()); ++it)
{
if (it->empty() || it->blocked())
continue;
- r_ = (reinterpret_cast<call_type>(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1)));
+ r_ = (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
}
}
@@ -211,24 +207,20 @@ FOR(1, $1,[
* function for the case that no accumulator is used and the
* return type is @p void.
*/
-template <LOOP(class T_arg%1, $1)>
-struct signal_emit$1<LIST(void, nil, LOOP(T_arg%1, $1))>
+template <class... T_arg>
+struct signal_emit$1<void, nil, T_arg...>
{
- typedef signal_emit$1<LIST(void, nil, LOOP(T_arg%1, $1))> self_type;
+ typedef signal_emit$1<void, nil, T_arg...> self_type;
typedef void result_type;
- typedef slot<LIST(void, LOOP(T_arg%1, $1))> slot_type;
+ typedef slot<void, T_arg...> slot_type;
typedef signal_impl::const_iterator_type iterator_type;
typedef ifelse($1,0,void (*call_type)(slot_rep*),typename slot_type::call_type call_type);
/** Executes a list of slots using an accumulator of type @e T_accumulator.dnl
-ifelse($1,0,,[
- * The arguments are passed directly on to the slots.])
- * @param first An iterator pointing to the first slot in the list.
- * @param last An iterator pointing to the last slot in the list.dnl
-FOR(1, $1,[
- * @param _A_a%1 Argument to be passed on to the slots.])
+ * The arguments are passed directly on to the slots.
+ * @param _A_a Arguments to be passed on to the slots.
*/
- static result_type emit(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
+ static result_type emit(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
{
if (!impl || impl->slots_.empty()) return;
signal_exec exec(impl);
@@ -238,19 +230,17 @@ FOR(1, $1,[
{
if (it->empty() || it->blocked())
continue;
- (reinterpret_cast<call_type>(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1)));
+ (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
}
}
/** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.dnl
-ifelse($1,0,,[
- * The arguments are passed directly on to the slots.])
+ * The arguments are passed directly on to the slots.
* @param first An iterator pointing to the first slot in the list.
* @param last An iterator pointing to the last slot in the list.dnl
-FOR(1, $1,[
- * @param _A_a%1 Argument to be passed on to the slots.])
+ * @param _A_a Arguments to be passed on to the slots.
*/
- static result_type emit_reverse(LIST(signal_impl* impl, LOOP(type_trait_take_t<T_arg%1> _A_a%1, $1)))
+ static result_type emit_reverse(signal_impl* impl, type_trait_take_t<T_arg>... _A_a)
{
if (!impl || impl->slots_.empty()) return;
signal_exec exec(impl);
@@ -266,7 +256,7 @@ FOR(1, $1,[
{
if (it->empty() || it->blocked())
continue;
- (reinterpret_cast<call_type>(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1)));
+ (reinterpret_cast<call_type>(it->rep_->call_))(it->rep_, _A_a...);
}
}
};
@@ -567,6 +557,8 @@ divert(0)
#include <sigc++/trackable.h>
#include <sigc++/functors/slot.h>
#include <sigc++/functors/mem_fun.h>
+#include <tuple>
+#include <utility>
//TODO: See comment in functor_trait.h.
#if defined(nil) && defined(SIGC_PRAGMA_PUSH_POP_MACRO)