PPMOC

PPMOC is a replacement for the Qt's moc compiler for template classes. Its main feature include:
  • Entirely implemented using the boost preprocessor library. Yes, this means you don't have to call any external tools !
  • Unlike Qt's moc, all macros are fully processed. For instance you can write any wrapper macros on top of PPMOC to simplify the generation of redundant declarations.
  • Allows to use all the Qt's meta object mechanisms (signals, slots, properties, reflexivity, etc.) with templated classes !
  • The types of your properties, signals and slots can be either typedef-ined types or templated types, or even #defined types.
Of course, there are some limitations:
  • You need a little of extra work to declare your slots and signals (see the example).
  • Currently all signals and slots are assumed to be public.
Here is an example:

MyClass.h

#include <ppmoc.h>

namespace MyNamespace {

template <typename Scalar>
class MyClass : public QObject
{
Q_OBJECT_X
public:

  MyClass()
  {
    connect(this, SIGNAL(asignal(Scalar)), this, SLOT(setValue(Scalar)));
  }

  enum AnEnum {Val0,Val1,Val2};

  void triggerASignal() {emit asignal(21.59);}

  Scalar getValue(void) const { return mValue; }
  void setValue(Scalar v) { mValue = v; }

  AnEnum getEnum(void) const { return mEnumValue; }
  void setEnum(AnEnum m) { mEnumValue = m; }

signals:

  void asignal(Scalar x);

protected:

  Scalar mValue;
  AnEnum mEnumValue;

};

typedef MyClass<float>  MyClassf;
typedef MyClass<double> MyClassd;

#define MyClassDeclaration PPMOC_MAKE_TPL_DECLARATION(\
    (1,(typename Scalar)), \
    MyNamespace,MyClass,QObject, \
    \
    PPMOC_CLASSINFO("Description","An example of PPMOC.") \
    PPMOC_SLOT(Scalar, getValue, ) \
    PPMOC_SLOT(, setValue, PPMOC_ARG(Scalar,v)) \
    PPMOC_PROPERTY(Value, Scalar, getValue, setValue, Designable) \
    PPMOC_PROPERTY(EnumValue, AnEnum, getEnum, setEnum, Designable) \
    PPMOC_SIGNAL(asignal, PPMOC_ARG(Scalar,x)) \
    PPMOC_ENUMS(AnEnum,3,(Val0,Val1,Val2)) \
  )

}

MyClass.cpp

#include "MyClass.h"

namespace MyNamespace {

PPMOC_DECLARE_TPL(MyClassDeclaration); // do it only once
PPMOC_INSTANCIATE_TPL(MyClassDeclaration,MyClassf); // one call per instanciation
PPMOC_INSTANCIATE_TPL(MyClassDeclaration,MyClassd);

template class MyClass<float>;
template class MyClass<double>;

}
The major difference with the standard Qt's moc compiler is the use of special macros to declare the meta class info, slots, signals, properties and enumerators. In particular you have to somehow duplicate the definitions of your slots and signals as well as the enumerator values. In this example we define the macro MyClassAddMocInstanciation() to make easier the use of new instanctiations of MyClass. For example, we only provide explicit instanciation for the float and double types. If someone want to use MyClass<int>, then he simply has to do:
typedef MyClass<int>  MyClassi;
PPMOC_INSTANCIATE_TPL(MyClassDeclaration,MyClassi);
Note that you can also cook your one macro to declare a property and its two slots in a single command. In most cases you only need two arguments: the type and the name of the property. The set and get function names can be deducted from the property name. The source code is a single header file ppmoc.h provided "as is" under the GNU LGPL v3. Feedback is welcome.