From d8028ede64c5e8e3f1611a0c0c34690ee14e8f0d Mon Sep 17 00:00:00 2001 From: Konrad Rosenbaum Date: Wed, 29 Feb 2012 19:31:07 +0100 Subject: [PATCH] add more docu for variadic lambda wrap --- src/misc/vlambda.cpp | 4 +- src/misc/vlambda.h | 93 +++++++++++++++++++++++++++++++++++--------------- src/misc/vlambda_p.h | 28 ++++++++++++++- 3 files changed, 93 insertions(+), 32 deletions(-) diff --git a/src/misc/vlambda.cpp b/src/misc/vlambda.cpp index 04d8c4d..bbaead2 100644 --- a/src/misc/vlambda.cpp +++ b/src/misc/vlambda.cpp @@ -11,7 +11,7 @@ // #include "vlambda.h" -#include +// #include using namespace std; using namespace MVLambdaNS; @@ -51,7 +51,7 @@ qt_meta_data({ // content: 0 // eod }) { - qDebug()<<"instantiated "< #include "vlambda_p.h" +/// @cond HIDDEN_CODE + /// Namespace for functions and sub-templates that are internal to the variadic lambda wrapper MVLambda. namespace MVLambdaNS { -/// \internal workarout for missing "final" keyword in GCC 4.6 +/// workarout for missing "final" keyword in GCC 4.6 //TODO: remove this as soon as "final" is available class MVLFinal{protected:MVLFinal(){}}; -/// \internal base class for variadic lambda wrapper +/// abstract base class for variadic lambda wrapper, simulates most of the Q_OBJECT macro +/// you do not need to understand the details, unless you want to enhance it or fix bugs class MVLambdaBase:public QObject { + ///amount of parameters const int m_count; + ///store the call-signature const QByteArray m_callparm,m_callret; + ///pointers into the meta data uint qt_meta_data[20]; + ///the mata data of the artificial slot QByteArray string_metadata; + ///the meta object of this instance, not static since it is calculated QMetaObject meta_object; + ///overridden by the template to implement the actual call virtual void do_call(void**)=0; + ///used by Qt to schedule a call static void qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a); + ///simulated extra meta data of the lambda class in general static const QMetaObjectExtraData staticMetaObjectExtraData; protected: -// MVLambdaBase(const MVLambdaBase&m):QObject(parent()),m_callname(m.m_callname){} + ///instantiates the instance, used by the template MVLambdaBase ( int c,QByteArray rt, QByteArray cn, QObject* parent); - const QByteArray callParams()const{return m_callparm;} - const QByteArray callReturn()const{return m_callret;} - - /*static void qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) - { - if (_c == QMetaObject::InvokeMetaMethod) { - Q_ASSERT(staticMetaObject.cast(_o)); - MVLambda *_t = static_cast *>(_o); - if (_id==0)MVLambdaNS::Call(_a,_t->call(); - } - Q_UNUSED(_a); - }*/ public: + ///returns a pointer to the meta object of this instance (never manipulate it!) const QMetaObject *metaObject() const{return &meta_object;} + ///cast function, used by Qt void *qt_metacast(const char *_clname); + ///used by Qt to deliver a call int qt_metacall(QMetaObject::Call _c, int _id, void **_a); - + + ///returns the parameter types of the call method + const QByteArray callParams()const{return m_callparm;} + ///returns the return type of the call method + const QByteArray callReturn()const{return m_callret;} }; //end of namespace }; +/// @endcond +///forward declare the lambda wrapper template templateclass MVLambda; -///wrapper for simple lambda expression, so it can be used with signals +/** \brief Wrapper for lambda expression, so it can be used with signals. + +This template allows to connect any lambda expression (or closure, function pointer, object method pointer or functor object) to a signal with compatible argument types by creating a slot with identical signature. + +In its simplest form the slot and lambda expression take no argument and return no values: +\code +int x=55; +QPushButton button("Push me!"); +MVLambda lambda([&x](){qDebug()<<"x is"< lambda([](double d,int i)->int{return d*i;}); +connect(&someobject,SIGNAL(mysig(double,int)),&lambda,SLOT(call(double,int))); +... +\endcode + +The wrapper object will automatically tell Qt about its virtual slot call(...) and will make sure it is called when a connected signal triggers. You can also request its meta object and inquire about its properties. Instances of this template are derived from QObject, so all functionality available in QObject is also available in lambda wrappers. + +\param Ret return type of the lambda being wrapped, also the return type of the generated slot +\param Args variadic list of types of the argument list of the lambda and slot +*/ template class MVLambda :public MVLambdaNS::MVLambdaBase,virtual private MVLambdaNS::MVLFinal { private: + ///function pointer... std::functionm_ptr; - /// \internal interface for the Qt meta object system + /// interface for the Qt meta object system virtual void do_call(void**a){ MVLambdaNS::Call(a,[&](Args...args)->Ret{return this->call(args...);}); } public: - ///instantiates the lambda object, e.g. - /// \code - ///int x=55; - ///QPushButton button("Push me!"); - ///MLambda lambda([&x](){qDebug()<<"x is"<l,QObject* parent = 0) :MVLambdaBase(MVLambdaNS::Count::count, MVLambdaNS::TypeStr::get(), MVLambdaNS::TypeStr::get(), parent), m_ptr(l){} - ///generic slot that transparently executes the lambda expression + ///overwrites the lambda/function that is executed as slot, this does + ///not alter signal-slot-connections + /// \param l new lambda, functor, function or method pointer + void setFunction(std::functionl) + {m_ptr=l;} + + ///Generic slot that transparently executes the lambda expression. + ///If the wrapper was initialized with a nullptr this slot will return a default constructed instance of the return type. + /// \param Args variadic list of arguments (depends on template parameters) + /// \returns an object of the configured return type - either the result of the lambda or a default constructed object Ret call(Args...args){if(m_ptr)return m_ptr(args...);else return Ret();} }; diff --git a/src/misc/vlambda_p.h b/src/misc/vlambda_p.h index 941e09d..7fa470b 100644 --- a/src/misc/vlambda_p.h +++ b/src/misc/vlambda_p.h @@ -18,10 +18,13 @@ #include #include +/// @cond HIDDEN_CODE + namespace MVLambdaNS { -/// \internal helper for lambda template: determines the string representation of the functions type signature +/// helper for lambda template: determines the string representation of the functions type signature templateclass TypeStr; +///recursive version: determines all typenames for more than one type in an argument list template class TypeStr{ public: @@ -29,39 +32,46 @@ static const QByteArray get() {return TypeStr::get()+","+TypeStr::get();} }; +///determines name of a simple type template class TypeStr{ public: static const QByteArray get() {T t;return QVariant::fromValue(t).typeName();} }; +///determines name of a reference type template class TypeStr{ public: static const QByteArray get() {T t;return QByteArray(QVariant::fromValue(t).typeName())+"&";} }; +///determine name of a const reference type template class TypeStr{ public: static const QByteArray get() {T t;return QByteArray("const ")+QVariant::fromValue(t).typeName()+"&";} }; +///determine name of a pointer type template class TypeStr{ public: static const QByteArray get() {T t;return QByteArray(QVariant::fromValue(t).typeName())+"*";} }; +///determine name of a const pointer type template class TypeStr{ public: static const QByteArray get() {T t;return QByteArray("const ")+QVariant::fromValue(t).typeName()+"*";} }; +///fallback for no argument list: returns empty string template<> class TypeStr<>{ public: static const QByteArray get() {return QByteArray();} }; +///returns empty string for a void argument list template<> class TypeStr{ public: static const QByteArray get() @@ -71,16 +81,24 @@ public: static const QByteArray get() ////////////////////////////////////////////////////// +///template to count an argument list templateclass Count; +///recursive version to count a list with at least one element template class Count{public: static const int count=Count::count + 1;}; +///fallback to count an empty argument list or to terminate a list template<> class Count<>{public: static const int count=0;}; + + + /////////////////////////////////////////////////////// +///wrapper type to turn a Qt internal meta call into an actual method call - it turns a void** list into a typed argument list and a return argument templateclass Call; +///turns a Qt internal meta call into a method call with return type and multiple arguments template class Call { @@ -92,6 +110,7 @@ class Call if(vl[0])*reinterpret_cast(vl[0])=r; } }; +///turns a Qt internal meta call into a method call with return type and a single argument template class Call { @@ -102,6 +121,7 @@ class Call if(vl[0])*reinterpret_cast(vl[0])=r; } }; +///turns a Qt internal meta call into a method call with return type and no arguments template class Call { @@ -113,7 +133,7 @@ class Call } }; - +///turns a Qt internal meta call into a method call returning void and multiple arguments template class Call { @@ -123,6 +143,7 @@ class Call Call(vl+1,[&](Args...args){cb(*reinterpret_cast(vl[1]),args...);}); } }; +///turns a Qt internal meta call into a method call returning void and a single argument template class Call { @@ -132,6 +153,7 @@ class Call cb(*reinterpret_cast(vl[1])); } }; +///turns a Qt internal meta call into a method call returning void and no arguments template<> class Call { @@ -145,4 +167,6 @@ class Call //end of namespace }; +/// @endcond + #endif -- 1.7.2.5