add more docu for variadic lambda wrap
authorKonrad Rosenbaum <konrad@silmor.de>
Wed, 29 Feb 2012 18:31:07 +0000 (19:31 +0100)
committerKonrad Rosenbaum <konrad@silmor.de>
Wed, 29 Feb 2012 18:31:07 +0000 (19:31 +0100)
src/misc/vlambda.cpp
src/misc/vlambda.h
src/misc/vlambda_p.h

index 04d8c4d..bbaead2 100644 (file)
@@ -11,7 +11,7 @@
 //
 
 #include "vlambda.h"
-#include <QDebug>
+// #include <QDebug>
 
 using namespace std;
 using namespace MVLambdaNS;
@@ -51,7 +51,7 @@ qt_meta_data({ // content:
         0 // eod
 })
 {
-       qDebug()<<"instantiated "<<QString("%2 call(%1)").arg(cn.data()).arg(rt.data());
+//     qDebug()<<"instantiated "<<QString("%2 call(%1)").arg(cn.data()).arg(rt.data());
        //init string data and meta data array
        string_metadata=QByteArray("MVLambda\0\0call(",15)+cn+QByteArray(")\0",2);
        qt_meta_data[15]=string_metadata.size();
index 3c422e8..14fbbea 100644 (file)
 #include <QObject>
 #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<Ret(Args...)> *_t = static_cast<MVLambda<Ret(Args...)> *>(_o);
-                       if (_id==0)MVLambdaNS::Call<Args...>(_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
 template<typename _Signature>class 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<void()> lambda([&x](){qDebug()<<"x is"<<x;});
+connect(&button,SIGNAL(clicked()),&lambda,SLOT(call()));
+button.show();
+\endcode
+the above code will show the value of the variable 'x' whenever the user clicks the button.
+
+A more complex variation takes arguments and returns a value:
+\code
+MVLambda<int(double,int)> 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<typename Ret,typename...Args>
 class MVLambda<Ret(Args...)> :public MVLambdaNS::MVLambdaBase,virtual private MVLambdaNS::MVLFinal
 {
        private:
+               ///function pointer...
                std::function<Ret(Args...)>m_ptr;
-               /// \internal interface for the Qt meta object system
+               /// interface for the Qt meta object system
                virtual void do_call(void**a){
                        MVLambdaNS::Call<Ret(Args...)>(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"<<x;});
-               ///connect(&button,SIGNAL(clicked()),&lambda,SLOT(call()));
-               ///button.show();
-               /// \endcode
-               ///the above code will show the value of the variable 'x' whenever the user clicks the button
+               ///instantiates the lambda wrapper object
+               /// \param l the lambda, closure, functor, function or method pointer to execute as a slot
+               /// \param parent optional: the parent object of this wrapper, you can use this to limit the lifetime of the wrapper object
                MVLambda(std::function<Ret(Args...)>l,QObject* parent = 0)
                :MVLambdaBase(MVLambdaNS::Count<Args...>::count, MVLambdaNS::TypeStr<Ret>::get(), MVLambdaNS::TypeStr<Args...>::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::function<Ret(Args...)>l)
+               {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();}
 };
 
index 941e09d..7fa470b 100644 (file)
 #include <QVariant>
 #include <QByteArray>
 
+/// @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
 template<typename...A>class TypeStr;
 
+///recursive version: determines all typenames for more than one type in an argument list
 template <typename F,typename...Args> 
 class TypeStr<F,Args...>{
 public:
@@ -29,39 +32,46 @@ static const QByteArray get()
 {return TypeStr<F>::get()+","+TypeStr<Args...>::get();}
 };
 
+///determines name of a simple type
 template <typename T> 
 class TypeStr<T>{
 public: static const QByteArray get()
 {T t;return QVariant::fromValue(t).typeName();}
 };
 
+///determines name of a reference type
 template <typename T> 
 class TypeStr<T&>{
 public: static const QByteArray get()
 {T t;return QByteArray(QVariant::fromValue(t).typeName())+"&";}
 };
+///determine name of a const reference type
 template <typename T> 
 class TypeStr<const T&>{
 public: static const QByteArray get()
 {T t;return QByteArray("const ")+QVariant::fromValue(t).typeName()+"&";}
 };
+///determine name of a pointer type
 template <typename T> 
 class TypeStr<T*>{
 public: static const QByteArray get()
 {T t;return QByteArray(QVariant::fromValue(t).typeName())+"*";}
 };
+///determine name of a const pointer type
 template <typename T> 
 class TypeStr<const T*>{
 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<void>{
 public: static const QByteArray get()
@@ -71,16 +81,24 @@ public: static const QByteArray get()
 
 
 //////////////////////////////////////////////////////
+///template to count an argument list
 template<typename ...Args>class Count;
 
+///recursive version to count a list with at least one element
 template<typename T,typename ...Args>
 class Count<T,Args...>{public: static const int count=Count<Args...>::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
 template<typename Sig>class Call;
 
+///turns a Qt internal meta call into a method call with return type and multiple arguments
 template<typename R,typename T,typename...Args>
 class Call<R(T,Args...)>
 {
@@ -92,6 +110,7 @@ class Call<R(T,Args...)>
                        if(vl[0])*reinterpret_cast<R*>(vl[0])=r;
                }
 };
+///turns a Qt internal meta call into a method call with return type and a single argument
 template<typename R,typename T>
 class Call<R(T)>
 {
@@ -102,6 +121,7 @@ class Call<R(T)>
                        if(vl[0])*reinterpret_cast<R*>(vl[0])=r;
                }
 };
+///turns a Qt internal meta call into a method call with return type and no arguments
 template<typename R>
 class Call<R()>
 {
@@ -113,7 +133,7 @@ class Call<R()>
                }
 };
 
-
+///turns a Qt internal meta call into a method call returning void and multiple arguments
 template<typename T,typename...Args>
 class Call<void(T,Args...)>
 {
@@ -123,6 +143,7 @@ class Call<void(T,Args...)>
                        Call<void(Args...)>(vl+1,[&](Args...args){cb(*reinterpret_cast<T*>(vl[1]),args...);});
                }
 };
+///turns a Qt internal meta call into a method call returning void and a single argument
 template<typename T>
 class Call<void(T)>
 {
@@ -132,6 +153,7 @@ class Call<void(T)>
                        cb(*reinterpret_cast<T*>(vl[1]));
                }
 };
+///turns a Qt internal meta call into a method call returning void and no arguments
 template<>
 class Call<void()>
 {
@@ -145,4 +167,6 @@ class Call<void()>
 //end of namespace
 };
 
+/// @endcond
+
 #endif