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);
206 # else //QGLIB_HAVE_CXX0X 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 219 # endif //QGLIB_HAVE_CXX0X 222 #else // !defined(BOOST_PP_IS_ITERATING) || !BOOST_PP_IS_ITERATING 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 346 #endif // !defined(BOOST_PP_IS_ITERATING) || !BOOST_PP_IS_ITERATING Wrappers for Glib and GObject classes.
Wrapper class for GValue.
bool connect(void *instance, const char *detailedSignal, T *receiver, R(T::*slot)(Args...), ConnectFlags flags=0)
Wrapper class for GQuark.