如何编写具有可变数量参数的宏来定义函数?假设我们使用2个参数定义类class1
,使用三个参数定义类class2
。
class class1 {
public:
int arg1;
int arg2;
class1(int x1, int x2): arg1(x1), arg2(x2) {}
};
class class2 {
public:
int arg1;
int arg2;
int arg3;
class1(int x1, int x2, int x3): arg1(x1), arg2(x2), arg3(x3) {}
};
对于我定义的每个类,甚至是在我想编写以下内容之前定义的类:
template<> inline void writeInfo<class1>(const class1& obj, FILE* fp) {
writeAmount(2, fp);
writeName("arg1", fp);
writeInfo(obj.arg1, fp);
writeName("arg2", fp);
writeInfo(obj.arg2, fp);
}
template<> inline void writeInfo<class2>(const class2& obj, FILE* fp) {
writeAmount(3, fp);
writeName("arg1", fp);
writeInfo(obj.arg1, fp);
writeName("arg2", fp);
writeInfo(obj.arg2, fp);
writeName("arg3", fp);
writeInfo(obj.arg3, fp);
}
我们无需关心writeAmount
,writeName
或writeInfo
的定义。我想做的是写点:
MACROWRITEINFO(class1, 2, arg1, arg2);
MACROWRITEINFO(class2, 3, arg1, arg2, arg3);
是否可以创建此类宏以便它可以扩展到上面的模板定义?我已经在很多地方读到了宏是邪恶的,但在这种情况下我相信它们非常有用,因为它们会减少我输入的代码量,从而减少我在创建过程中会产生的拼写错误。模板功能。
答案 0 :(得分:5)
首先,您应该改进格式/代码。您的代码在类定义后缺少“类”关键字和分号 - 当您发布代码段时,请确保它是正确的代码,因为有些人(即我)会尝试编译它。
其次,不要使用函数模板专业化。如果宏是邪恶的,那么它们必须是撒旦的化身。坚持好旧的超载。有关详细信息,请参阅here。
至少 - 一个答案。如果所有 args属于同一类型,您可以使用可变参数宏 - 例如,您可以在writeInfo函数内创建一个数组并迭代元素。由于这里的情况并非如此,因此您可以为不同数量的参数定义MACROWRITEINFO宏的许多变体,使用一些常见的块来减少代码重复。例如:
#define MACROWRITEINFO_BEGIN(type, amount) \
void writeInfo(const type& obj, FILE* fp) \
{ \
writeAmount(amount, fp);
#define MACROWRITEINFO_NAMEINFO(name) \
writeName(#name, fp); \
writeInfo(obj.##name, fp);
#define MACROWRITEINFO_END() \
}
使用那些,您现在可以根据参数的数量定义变体。
#define MACROWRITEINFO1(type, arg1) \
MACROWRITEINFO_BEGIN(type, 1) \
MACROWRITEINFO_NAMEINFO(arg1) \
MACROWRITEINFO_END()
#define MACROWRITEINFO2(type, arg1, arg2) \
MACROWRITEINFO_BEGIN(type, 2) \
MACROWRITEINFO_NAMEINFO(arg1) \
MACROWRITEINFO_NAMEINFO(arg2) \
MACROWRITEINFO_END()
等等......
编辑: 好吧,我想 可以在这里使用可变参数宏。看看这个SO question。这是纯粹的疯狂,但你应该能够实现你想要的。
编辑: 我的想法是将可变参数扩展到数组然后迭代它们;如果他们是相同的类型,让我们说int,你可以写:
#define VAARGSSAMPLE(...) \
int args[] = { __VA_ARGS__ }; \
for (int i = 0; i < sizeof(args)/sizeof(int); ++i) \
{ \
printf("%d\n", args[i]); \
}
VAARGSSAMPLE(1, 5, 666);
因此,如果所有变量都属于同一类型,则可以将它们放在数组中。但它们不是,所以它不会这样做。如果你真的,真的想坚持使用可变参数,请转到我的第一次编辑。
答案 1 :(得分:1)
我认为用宏来做这件事是不可能的。您可以使用变量参数(可变参数),但不能生成依赖于参数的代码。
我建议你创建一个DSL(例如简单的xml ..)并从中生成代码。这是更清洁和良好的做法。
你可以这样做:
<writeInfos>
<writeInfo class="class1" amount="3">
<arguments>
<argument>arg1</argument>
<argument>arg2</argument>
</arguments>
</writeInfo>
</writeInfos>
然后从中创建源代码。您应该在构建过程中添加此步骤..
但你也可以定义更简单的东西..你可以将你的MACROWRITEINFO“函数”放在一个文本文件中并自己解析它。