I am trying to create a map containing constructor functions. In order to do that I am using this method:
automatic registration of object creator function with a macro
So in a DLL I have data structures like that:
namespace pods
{
struct PODS_API StructExample{
double d;
bool b;
int i;
StructExample() : d(0), b(false), i(0) {};
StructExample(QList<QVariant> paramList) :
d(paramList[0].toDouble()),
b(paramList[1].toBool()),
i(paramList[2].toInt())
{};
StructExample(double param_d, bool param_b, int param_i) : d(param_d), b(param_b), i(param_i) {};
};
REGISTER_VARIABLE_TYPE(StructExample);
}
I am trying to make a Factory which will call the right constructor (implementing the right structure).
Those structures are contained in an object I call VariableT. This is a template class like that:
namespace variable{
template <class T>
class VariableT : public AbstractVariableT<T>, public IVariable {
public:
VariableT() {};
VariableT(const QString& name, const QList<QVariant> listParam) : name(name), item(T(listParam)) {};
~VariableT(){};
T* getData()
{
return &item;
};
void setData(T* t)
{
item = *t;
};
private:
T item;
};
}
When calling VariableT with the right T (i.e. StructExample) I can implement a container for those structures. VariableT inherit from IVariable so I can then use reference to those containers as IVariable in any map in my program.
Now I am trying to make a function inspired from the example I quoted before.
This will allow me to add structures and use them in my program with a minimum of code change.
I made my VariableT (container of struct) inherit from AbstractVariableT.
namespace variable
{
#define REGISTER_VARIABLE_TYPE(T) bool isRegistered_##T = \
VariableFactory::instance()-> \
regVariable<T>(#T, (VariableT<T>::createVariable)(const QString&, const QList<QVariant>&));
template <class T>
class AbstractVariableT : public QObject
{
public:
static IVariable* createVariable(const QString& name, const QList<QVariant>& listParam) { return new VariableT<T>(name,listParam); }
virtual ~AbstractVariableT(){};
protected:
QString name;
};
}
In this class I'm using a function createVariable to call the constructor methods of VariableT. Since AbstractVariableT is a template class, depending on the type of Struct used it will call a different constructor.
In order to call the createVariable function I am using a class I called VariableFactory:
namespace variable
{
class VariableFactory
{
public:
static VariableFactory* instance();
static IVariable* createVariable(const QString& idVariable, const QString& name, const QList<QVariant>& listParam);
template <class T>
bool regVariable(const QString& idVariable, IVariable* (*creator)(const QString&, const QList<QVariant>&))
{
variableCreators[idVariable] = creator;
return true;
}
private:
QMap<QString, IVariable* (*)(const QString&, const QList<QVariant>&)> variableCreators;
};
}
In this class I store a map called variableCreator of my CreateVariable methods. (i.e. one map key/value will be :
"StructExample"/AbstractVariableT::CreateVariable<StructExample>(const QString& name, const QList<QVariant>& listParam);
or something like that.. ).
In order to add constructor in the map I am using the function regVariable.
In order to automaticaly add every constructor for different StructContainer I want to use a macro which will call regVariable.
#define REGISTER_VARIABLE_TYPE(T) bool isRegistered_##T = VariableFactory::instance()->regVariable<T>(#T, (VariableT<T>::createVariable)(const QString&, const QList<QVariant>&));
And I used this in my factory (depending on my type it get me the correct function from my map and use those parameters for the function :
IVariable* VariableFactory::createVariable(const QString& typeVariable, const QString& name, const QList<QVariant>& listParam)
{
return instance()->variableCreators[typeVariable](name, listParam);
}
I can't find the correct syntax to do it. Or can I even do it this way ?
When I try to use the macro under my Struct (StructExample). I get different errors.
It looks like I can't register the constructor correctly :
Error 1 error C2653: 'VariableFactory' : is not a class or namespace name
Error 5 error C2275: 'pods::StructExample' : illegal use of this type as an expression
Error 2 error C2227: left of '->regVariable' must point to class/struct/union/generic type
Error 8 error C2143: syntax error : missing ')' before 'const'
Error 4 error C2065: 'VariableT' : undeclared identifier
Error 7 error C2065: 'createVariable' : undeclared identifier
Error 9 error C2059: syntax error : ')'
Error 3 error C2039: 'VariableT' : is not a member of 'variable'
Error 6 error C2039: 'createVariable' : is not a member of '`global namespace''
Error 10 error C1903: unable to recover from previous error(s); stopping compilation
This question was edited.
Thanks for helping. Eric