使用具有可变数量参数的宏编写函数

时间:2011-07-22 08:07:11

标签: c++

如何编写具有可变数量参数的宏来定义函数?假设我们使用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);
}

我们无需关心writeAmountwriteNamewriteInfo的定义。我想做的是写点:

MACROWRITEINFO(class1, 2, arg1, arg2);
MACROWRITEINFO(class2, 3, arg1, arg2, arg3);

是否可以创建此类宏以便它可以扩展到上面的模板定义?我已经在很多地方读到了宏是邪恶的,但在这种情况下我相信它们非常有用,因为它们会减少我输入的代码量,从而减少我在创建过程中会产生的拼写错误。模板功能。

2 个答案:

答案 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“函数”放在一个文本文件中并自己解析它。