如下所示,定义一个宏函数,只要传入类型名,即可生成一个类模板
#include <QList>
#include <QVariant>
#include <QMetaType>
#include <typeinfo>
#include <type_traits>
#include <QStringList>
#define FIELD_NAME(cls) CLASS_NAME(cls)
#define GENERATE_FIELD_CLASS(classname) \
template <typename T> struct classname##Field \
{\
FIELD_NAME(#classname)\
public:\
classname##Field(){}\
classname##Field(T val){ value.append(val);}\
classname##Field(QList<T> val) : value(val){}\
\
bool IsField(){return true;}\
KlarfNodeAttribute Attribute(){ return E_Field;}\
\
const QList<T> GetValue() const {return value;}\
void SetValue(const QList<T>& val){value = val;}\
void AppendValue(const T& val){ value.append(val);}\
bool RemoveAt(const int index){\
if(index >= value.count()) {return false;}\
value.removeAt(index);return true;\
}\
void InsertValue(int i,const T& val){value.insert(i,val);}\
\
using Self = classname##Field;\
\
virtual Self fromString(const QString& s){ (void)s;return* this;}\
virtual const QString toString(const QString& indent = default_indent)const { return QString();}\
\
private:\
QList<T> value;\
};
/**/
类模板的偏特化 :通过宏函数指定类名及特化类型即可
/// int uint long ulong longlong ulonglong float
#define GENERATE_FIELD_CLASS_WITH_INTEGER_TYPE(classname,T) \
template<> struct classname##Field<T>\
{\
FIELD_NAME(#classname)\
public:\
classname##Field(){}\
classname##Field(T val){ value.append(val);}\
classname##Field(QList<T> val) : value(val){}\
\
bool IsField(){return true;}\
KlarfNodeAttribute Attribute(){ return E_Field;}\
\
const QList<T> GetValue() const {return value;}\
void SetValue(const QList<T>& val){value = val;}\
void AppendValue(const T& val){ value.append(val);}\
bool RemoveAt(const int index){\
if(index >= value.count()) {return false;}\
value.removeAt(index);return true;\
}\
void InsertValue(int i,const T& val){value.insert(i,val);}\
\
using Self = classname##Field<T>;\
\
virtual Self fromString(const QString& s){ \
int ns = s.indexOf("{");\
int ne = s.indexOf("}");\
QString data;\
if( ns != -1 && ne != -1 ){\
data = s.mid(ns+1,ne-ns-1).trimmed();\
}\
if(!data.isEmpty()){\
QStringList dl = data.simplified().split(",",Qt::SkipEmptyParts);\
value.clear();\
if(#T == "int")\
foreach (auto ds, dl) value.append(ds.toInt());\
else if(#T == "uint" || #T == "unsigned int")\
foreach (auto ds, dl) value.append(ds.toUInt());\
else if(#T == "long")\
foreach (auto ds, dl) value.append(ds.toLong());\
else if(#T == "ulong" || #T == "unsigned long")\
foreach (auto ds, dl) value.append(ds.toULong());\
else if(#T == "long long")\
foreach (auto ds, dl) value.append(ds.toLongLong());\
else if(#T == "unsigned long long")\
foreach (auto ds, dl) value.append(ds.toULongLong());\
else if(#T == "float")\
foreach (auto ds, dl) value.append(ds.toFloat());\
else if(#T == "double")\
foreach (auto ds, dl) value.append(ds.toDouble());\
else qt_noop();\
}\
return *this; \
}\
virtual const QString toString(const QString& indent = default_indent)const {\
QString s = indent + QString("Field %1 %2 {").arg(#classname).arg(QString::number(value.count()));\
for(int i = 0; i < value.count();++i){\
s += QString::number(value[i],10);\
if(i != value.count() -1) s+=",";\
}\
s += "}";\
return s;\
}\
\
private:\
QList<T> value;\
};
/**/