18 #ifndef NURIA_CALLBACK_HPP
19 #define NURIA_CALLBACK_HPP
21 #include <type_traits>
24 #include <QSharedData>
29 #include "essentials.hpp"
30 #include "variant.hpp"
33 class CallbackPrivate;
36 namespace CallbackHelper {
37 template<
int ... Index >
45 typedef typename CreateIndexTuple< Size - 1 >::type::template append< Size - 1 > type;
53 template<
typename... Types >
54 using buildIndexTuple =
typename CreateIndexTuple<
sizeof...(Types) + 1 >::type;
57 template<
typename T >
58 constexpr
int typeId () {
return qMetaTypeId< T > (); }
61 constexpr
int typeId< void > () {
return 0; }
64 template<
typename T >
65 void getArguments (
void **list,
int *types,
int idx, T *cur) {
67 types[idx] = qMetaTypeId< typename std::remove_const< T >::type > ();
70 template<
typename T,
typename T2,
typename ... Args >
71 void getArguments (
void **list,
int *types,
int idx,
72 T *cur, T2 *next, Args * ... args) {
73 getArguments (list, types, idx, cur);
74 getArguments (list, types, idx + 1, next, args ...);
144 struct TrampolineBase;
145 template<
typename Ret,
typename ... Args >
struct MethodHelper;
146 template<
typename Class,
typename Ret,
typename ... Args >
struct MemberMethodHelper;
147 template<
typename FullType,
typename Ret,
typename ... Args >
struct LambdaHelper;
182 explicit Callback (QObject *receiver,
const char *slot,
bool variadic =
false);
188 template<
typename Ret,
typename ... Args >
189 Callback (Ret (*func)(Args ...),
bool variadic =
false)
190 : d (0) { setCallback (func); setVariadic (variadic); }
193 template<
typename Class,
typename Ret,
typename ... Args >
194 Callback (Class *instance, Ret (Class::*func)(Args ...),
bool variadic =
false)
195 : d (0) { setCallback (instance, func); setVariadic (variadic); }
197 template<
typename Ret,
typename ... Args >
198 Callback (
const std::function< Ret(Args ...) > &func,
bool variadic =
false)
199 : d (0) { setCallback (func); setVariadic (variadic); }
202 template<
typename Lambda >
204 Callback cb = fromLambdaImpl (l, &Lambda::operator());
224 bool operator== (
const Callback &other)
const;
227 bool isValid ()
const;
233 bool isVariadic ()
const;
236 void setVariadic (
bool variadic);
239 int returnType ()
const;
242 QList< int > argumentTypes ()
const;
249 template<
typename Ret,
typename ... Args >
250 bool setCallback (Ret (*func)(Args ...)) {
252 buildArgList< Args ... > (args);
253 return initBase (
new MethodHelper< Ret, Args ... > (func),
254 CallbackHelper::typeId< Ret > (), args);
258 template<
typename Class,
typename Ret,
typename ... Args >
259 bool setCallback (Class *instance, Ret (Class::*func)(Args ...)) {
261 buildArgList< Args ... > (args);
262 return initBase (
new MemberMethodHelper< Class, Ret, Args ... > (instance, func),
263 CallbackHelper::typeId< Ret > (), args);
267 template<
typename Ret,
typename ... Args >
268 bool setCallback (std::function< Ret(Args ...) > func) {
270 buildArgList< Args ... > (args);
271 return initBase (
new LambdaHelper< std::function< Ret(Args ...) >, Ret, Args ... > (func),
272 CallbackHelper::typeId< Ret > (), args);
276 bool setCallback (QObject *receiver,
const char *slot);
279 template<
typename Ret,
typename ... Args >
280 Callback &operator= (Ret (*func)(Args ...)) { setCallback (func);
return *
this; }
291 void bindList (
const QVariantList &arguments = QVariantList());
296 template<
typename Lambda,
typename ... Args >
298 Callback cb = fromLambdaImpl (func, &Lambda::operator());
308 template<
typename ... Args >
319 QVariant invoke (
const QVariantList &arguments)
const;
324 template<
typename ... Args >
325 QVariant operator() (
const Args &... args)
const {
326 void *list[
sizeof... (Args)];
327 int types[
sizeof... (Args)];
328 CallbackHelper::getArguments (list, types, 0, const_cast< Args * > (&args) ...);
329 return invoke (
sizeof... (Args), list, types);
333 inline QVariant operator() () {
334 return invoke (0, 0, 0);
339 friend class CallbackPrivate;
341 QVariant invoke (
int count,
void **args,
int *types)
const;
342 QVariant invokePrepared (
const QVariantList &arguments)
const;
345 QVariant invokeInternal (
int count,
void **args,
int *types)
const;
350 template<
typename T >
struct removeRef {
typedef T type; };
351 template<
typename T >
struct removeRef< T & >;
352 template<
typename T >
struct removeRef< const T & > {
typedef T type; };
357 template<
typename Lambda,
typename Ret,
typename ... Args >
358 inline static Callback fromLambdaImpl (Lambda l, Ret (Lambda::*)(Args ...)
const) {
359 return Callback (std::function< Ret(Args ...) > (l));
366 bool initBase (TrampolineBase *base,
int retType,
const QList< int > &args);
368 template<
typename T1,
typename ... T2 >
369 inline void buildArgListDo (QList< int > &list, T1 cur, T2 ... next) {
371 buildArgListDo (list, next ...);
374 template<
typename T >
375 inline void buildArgListDo (QList< int > &list, T cur)
376 { list.append (cur); }
379 inline void buildArgListDo (QList< int > &) { }
386 template<
typename ... Args >
387 inline void buildArgList (QList< int > &list) {
388 buildArgListDo (list, qMetaTypeId<
typename removeRef< Args >::type > () ...);
396 struct TrampolineBase {
398 TrampolineBase (Type t) : type (t) {}
400 virtual ~TrampolineBase () {}
401 virtual void trampoline (
void **) = 0;
404 struct MemberTrampolineBase : TrampolineBase {
405 MemberTrampolineBase (
void *inst) : TrampolineBase (MemberMethod), instance (inst) {}
410 template<
typename Ret,
typename ... Args >
411 struct MethodHelper :
public TrampolineBase {
412 typedef Ret (*Prototype)(Args ...);
415 MethodHelper (Prototype f) : TrampolineBase (StaticMethod), func (f) {}
417 template<
int ... Index >
418 inline void trampolineImpl (
void **args, CallbackHelper::IndexTuple< Index... >) {
419 (*
reinterpret_cast< typename removeRef< Ret >::type *
> (args[0])) =
420 func (*
reinterpret_cast< typename removeRef< Args >::type *
>(args[Index]) ...);
423 void trampoline (
void **args)
424 { trampolineImpl (args, CallbackHelper::buildIndexTuple< Args ... > ()); }
428 template<
typename ... Args >
429 struct MethodHelper< void, Args ... > :
public TrampolineBase {
430 typedef void (*Prototype)(Args ...);
433 MethodHelper (Prototype f) : TrampolineBase (StaticMethod), func (f) {}
435 template<
int ... Index >
436 inline void trampolineImpl (
void **args, CallbackHelper::IndexTuple< Index... >) {
438 func (*
reinterpret_cast< typename removeRef< Args >::type *
>(args[Index]) ...);
441 void trampoline (
void **args)
442 { trampolineImpl (args, CallbackHelper::buildIndexTuple< Args ... > ()); }
447 template<
typename Class,
typename Ret,
typename ... Args >
448 struct MemberMethodHelper :
public MemberTrampolineBase {
449 typedef Ret (Class::*Prototype)(Args ...);
452 MemberMethodHelper (Class *inst, Prototype f) : MemberTrampolineBase (inst), func (f) {}
454 template<
int ... Index >
455 inline void trampolineImpl (
void **args, CallbackHelper::IndexTuple< Index... >) {
456 (*
reinterpret_cast< typename removeRef< Ret >::type *
> (args[0])) =
457 (
reinterpret_cast< Class *
> (instance)->*func)
458 (*
reinterpret_cast< typename removeRef< Args >::type *
>(args[Index]) ...);
461 void trampoline (
void **args)
462 { trampolineImpl (args, CallbackHelper::buildIndexTuple< Args ... > ()); }
466 template<
typename Class,
typename ... Args >
467 struct MemberMethodHelper< Class, void, Args ... > :
public MemberTrampolineBase {
468 typedef void (Class::*Prototype)(Args ...);
471 MemberMethodHelper (Class *inst, Prototype f) : MemberTrampolineBase (inst), func (f) {}
473 template<
int ... Index >
474 inline void trampolineImpl (
void **args, CallbackHelper::IndexTuple< Index... >) {
476 (
reinterpret_cast< Class *
> (instance)->*func)
477 (*
reinterpret_cast< typename removeRef< Args >::type *
>(args[Index]) ...);
480 void trampoline (
void **args)
481 { trampolineImpl (args, CallbackHelper::buildIndexTuple< Args ... > ()); }
486 template<
typename FullType,
typename Ret,
typename ... Args >
487 struct LambdaHelper :
public TrampolineBase {
490 LambdaHelper (
const FullType &f) : TrampolineBase (Lambda), func (f) {}
492 template<
int ... Index >
493 inline void trampolineImpl (
void **args, CallbackHelper::IndexTuple< Index... >) {
494 (*
reinterpret_cast< typename removeRef< Ret >::type *
> (args[0])) =
495 func (*
reinterpret_cast< typename removeRef< Args >::type *
>(args[Index]) ...);
498 void trampoline (
void **args)
499 { trampolineImpl (args, CallbackHelper::buildIndexTuple< Args ... > ()); }
503 template<
typename FullType,
typename ... Args >
504 struct LambdaHelper< FullType, void, Args ... > :
public TrampolineBase {
507 LambdaHelper (
const FullType &f) : TrampolineBase (Lambda), func (f) {}
509 template<
int ... Index >
510 inline void trampolineImpl (
void **args, CallbackHelper::IndexTuple< Index... >) {
512 func (*
reinterpret_cast< typename removeRef< Args >::type *
>(args[Index]) ...);
515 void trampoline (
void **args)
516 { trampolineImpl (args, CallbackHelper::buildIndexTuple< Args ... > ()); }
528 Q_DECLARE_METATYPE(Nuria::Callback::Placeholder)
530 #endif // NURIA_CALLBACK_HPP
A modern style callback mechanism which can be bound to various method types including slots...
Definition: callback.hpp:141
Callback(Ret(*func)(Args...), bool variadic=false)
Definition: callback.hpp:189
Placeholder
Definition: callback.hpp:165
static QVariantList buildList(const Items &...items)
Definition: variant.hpp:547
Callback & bind(const Args &...args)
Definition: callback.hpp:309
static Callback boundLambda(Lambda func, const Args &...args)
Definition: callback.hpp:297
Callback(Class *instance, Ret(Class::*func)(Args...), bool variadic=false)
Definition: callback.hpp:194
Definition: callback.hpp:44
Type
Definition: callback.hpp:154
void setVariadic(bool variadic)
static Callback fromLambda(Lambda l, bool variadic=false)
Definition: callback.hpp:203
Definition: callback.hpp:38