19 #if !defined(BOOST_PP_IS_ITERATING) || !BOOST_PP_IS_ITERATING
21 # ifndef IN_QGLIB_CONNECT_H
22 # error "This file must not be included directly"
26 # include "refpointer.h"
27 # include <QtCore/QList>
30 # include <boost/type_traits.hpp>
39 template <
typename Function,
typename Signature>
45 template <
typename Function,
typename R>
48 static inline void invoke(
const Function & f, Value & result) { ValueImpl<R>::set(result, f()); }
51 template <
typename Function>
52 struct invoker<Function, void>
54 static inline void invoke(
const Function & f, Value &) { f(); }
70 template <
typename T,
typename R,
typename... Args>
74 inline MemberFunction(R (T::*fn)(Args...), T *obj)
75 : m_function(fn), m_object(obj) {}
77 inline R operator()(Args&&... args)
const
79 return (m_object->*m_function)(std::forward<Args>(args)...);
83 R (T::*m_function)(Args...);
87 template <
typename T,
typename R,
typename... Args>
88 MemberFunction<T, R, Args...> mem_fn(R (T::*fn)(Args...), T *obj)
90 return MemberFunction<T, R, Args...>(fn, obj);
96 template <
typename ParentFunction,
typename R,
typename Arg1,
typename... Args>
97 class BoundArgumentFunction
100 inline BoundArgumentFunction(ParentFunction && fn, Arg1 && arg)
101 : m_function(std::forward<ParentFunction>(fn)),
102 m_firstArg(std::forward<Arg1>(arg)) {}
104 inline R operator()(Args&&... args)
const
106 return m_function(std::forward<Arg1>(m_firstArg), std::forward<Args>(args)...);
110 ParentFunction && m_function;
114 template <
typename F,
typename R,
typename Arg1,
typename... Args>
115 inline BoundArgumentFunction<F, R, Arg1, Args...> partial_bind(F && f, Arg1 && a1)
117 return BoundArgumentFunction<F, R, Arg1, Args...>(std::forward<F>(f), std::forward<Arg1>(a1));
123 template <
typename F,
typename R>
124 inline void unpackAndInvoke(F &&
function, Value & result,
125 QList<Value>::const_iterator &&,
126 QList<Value>::const_iterator &&)
128 invoker<F, R>::invoke(
function, result);
131 template <
typename F,
typename R,
typename Arg1,
typename... Args>
132 inline void unpackAndInvoke(F &&
function, Value & result,
133 QList<Value>::const_iterator && argsBegin,
134 QList<Value>::const_iterator && argsEnd)
136 typedef typename boost::remove_const<
137 typename boost::remove_reference<Arg1>::type
139 typedef BoundArgumentFunction<F, R, Arg1, Args...> F1;
141 CleanArg1 && boundArg = ValueImpl<CleanArg1>::get(*argsBegin);
142 F1 && f = partial_bind<F, R, Arg1, Args...>(std::forward<F>(
function), std::forward<Arg1>(boundArg));
144 unpackAndInvoke< F1, R, Args... >(std::forward<F1>(f), result,
145 std::forward<QList<Value>::const_iterator>(++argsBegin),
146 std::forward<QList<Value>::const_iterator>(argsEnd));
152 template <
typename F,
typename R,
typename... Args>
153 struct CppClosure<F, R (Args...)>
155 class ClosureData :
public ClosureDataBase
158 inline ClosureData(
const F & func,
bool passSender)
159 : ClosureDataBase(passSender), m_function(func) {}
161 virtual void marshaller(Value & result,
const QList<Value> & params)
163 if (
static_cast<size_t>(params.size()) <
sizeof...(Args)) {
164 throw std::logic_error(
"The signal provides less arguments than what the closure expects");
167 unpackAndInvoke<F, R, Args...>(std::forward<F>(m_function), result,
168 params.constBegin(), params.constEnd());
175 static inline ClosureDataBase *create(
const F &
function,
bool passSender)
177 return new ClosureData(
function, passSender);
187 template <
typename T,
typename R,
typename... Args>
188 bool connect(
void *instance,
const char *detailedSignal,
189 T *receiver, R (T::*slot)(Args...), ConnectFlags flags = 0)
191 typedef Private::MemberFunction<T, R, Args...> F;
193 F && f = Private::mem_fn(slot, receiver);
194 Private::ClosureDataBase* && closure
195 = Private::CppClosure<F, R (Args...)>::create(f, flags &
PassSender);
197 return Private::connect(instance, detailedSignal,
Quark(),
198 receiver, Private::GetDestroyNotifier<T>(),
199 Private::hashMfp(slot), closure, flags);
208 # include <boost/function.hpp>
209 # include <boost/preprocessor.hpp>
210 # include <boost/bind.hpp>
213 # define BOOST_PP_ITERATION_PARAMS_1 (3,(0, QGLIB_CONNECT_MAX_ARGS, "QGlib/connectimpl.h"))
214 # include BOOST_PP_ITERATE()
216 # undef BOOST_PP_ITERATION_PARAMS_1
217 # undef QGLIB_CONNECT_MAX_ARGS
233 # define QGLIB_CONNECT_IMPL_NUM_ARGS \
236 # define QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_PARAMS \
237 BOOST_PP_ENUM_TRAILING_PARAMS(QGLIB_CONNECT_IMPL_NUM_ARGS, typename A)
239 # define QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_ARGS \
240 BOOST_PP_ENUM_TRAILING_PARAMS(QGLIB_CONNECT_IMPL_NUM_ARGS, A)
242 # define QGLIB_CONNECT_IMPL_TEMPLATE_ARGS \
243 BOOST_PP_ENUM_PARAMS(QGLIB_CONNECT_IMPL_NUM_ARGS, A)
250 # define QGLIB_CONNECT_IMPL_CPPCLOSUREN \
251 BOOST_PP_CAT(CppClosure, QGLIB_CONNECT_IMPL_NUM_ARGS)
253 # define QGLIB_CONNECT_IMPL_UNPACK_ARGS_STEP(z, n, list) \
255 typename boost::remove_const< \
256 typename boost::remove_reference<A ##n>::type \
260 # define QGLIB_CONNECT_IMPL_UNPACK_ARGS(list) \
261 BOOST_PP_REPEAT(QGLIB_CONNECT_IMPL_NUM_ARGS, QGLIB_CONNECT_IMPL_UNPACK_ARGS_STEP, list)
263 template <
typename F,
typename R QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_PARAMS>
264 struct QGLIB_CONNECT_IMPL_CPPCLOSUREN
266 class ClosureData :
public ClosureDataBase
269 inline ClosureData(
const F & func,
bool passSender)
270 : ClosureDataBase(passSender), m_function(func) {}
272 virtual void marshaller(Value & result,
const QList<Value> & params)
274 if (params.size() < QGLIB_CONNECT_IMPL_NUM_ARGS) {
275 throw std::logic_error(
"The signal provides less arguments than what the closure expects");
278 # if QGLIB_CONNECT_IMPL_NUM_ARGS > 0
279 boost::function<R ()> callback = boost::bind<R>(m_function
280 QGLIB_CONNECT_IMPL_UNPACK_ARGS(params));
281 invoker< boost::function<R ()>, R >::invoke(callback, result);
283 invoker< F, R >::invoke(m_function, result);
291 static ClosureDataBase *create(
const F &
function,
bool passSender)
293 return new ClosureData(
function, passSender);
298 template <
typename F,
typename R QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_PARAMS>
299 struct CppClosure<F, R (QGLIB_CONNECT_IMPL_TEMPLATE_ARGS)>
300 :
public QGLIB_CONNECT_IMPL_CPPCLOSUREN< F, R QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_ARGS >
304 # undef QGLIB_CONNECT_IMPL_UNPACK_ARGS
305 # undef QGLIB_CONNECT_IMPL_UNPACK_ARGS_STEP
306 # undef QGLIB_CONNECT_IMPL_CPPCLOSUREN
314 # define QGLIB_CONNECT_IMPL_BIND_ARGS \
315 BOOST_PP_COMMA_IF(QGLIB_CONNECT_IMPL_NUM_ARGS) \
316 BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(QGLIB_CONNECT_IMPL_NUM_ARGS), _)
318 template <
typename T,
typename R QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_PARAMS>
319 bool connect(
void *instance,
const char *detailedSignal,
320 T *receiver, R (T::*slot)(QGLIB_CONNECT_IMPL_TEMPLATE_ARGS), ConnectFlags flags = 0)
322 boost::function<R (QGLIB_CONNECT_IMPL_TEMPLATE_ARGS)> f
323 = boost::bind(slot, receiver QGLIB_CONNECT_IMPL_BIND_ARGS);
325 Private::ClosureDataBase *closure = Private::CppClosure<
326 boost::function<R (QGLIB_CONNECT_IMPL_TEMPLATE_ARGS)>,
327 R (QGLIB_CONNECT_IMPL_TEMPLATE_ARGS)
330 return Private::connect(instance, detailedSignal, Quark(),
331 receiver, Private::GetDestroyNotifier<T>(),
332 Private::hashMfp(slot), closure, flags);
335 # undef QGLIB_CONNECT_IMPL_BIND_ARGS
341 # undef QGLIB_CONNECT_IMPL_TEMPLATE_ARGS
342 # undef QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_ARGS
343 # undef QGLIB_CONNECT_IMPL_TRAILING_TEMPLATE_PARAMS
344 # undef QGLIB_CONNECT_IMPL_NUM_ARGS
Wrapper class for GQuark.
Wrappers for Glib and GObject classes.
bool connect(void *instance, const char *detailedSignal, T *receiver, R(T::*slot)(Args...), ConnectFlags flags=0)