简体   繁体   English

使用可变编号 arguments 的宏编写 function

[英]Writing a function using a macro with variable number of arguments

How do you write a macro with variable number of arguments to define a function?你如何编写一个可变数量的 arguments 的宏来定义一个 function? Suppose that we define the class class1 with 2 parameters and class class2 with three parameters.假设我们用 2 个参数定义 class class1 ,用三个参数定义 class 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) {}
};

For each class that I define or even classes that have been defined before I want to write the following:对于我定义的每个 class 甚至是在我想编写以下内容之前已经定义的类:

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);
}

We do not need to care about the definitions of writeAmount , writeName or writeInfo .我们不需要关心writeAmountwriteNamewriteInfo的定义。 What I would like to do is write something like:我想做的是写这样的东西:

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

Is it possible to create such macro so that it can expand to the above template definitions?是否可以创建这样的宏,以便它可以扩展到上述模板定义? I've read in a lot of places that macros are evil, but in this case I believe that they are very helpful since they'll reduce the amount of code I type and thus the amount of typos I'll make during the creation of the template functions.我在很多地方都读到宏是邪恶的,但在这种情况下,我相信它们非常有帮助,因为它们会减少我输入的代码量,从而减少我在创建模板函数。

First of all you should improve your formatting/code.首先,您应该改进您的格式/代码。 Your code lacks "class" keywords and semicolons after classes definitions - when you post a snippet make sure it's proper code, because some people (ie me) will try to compile it.您的代码在类定义后缺少“类”关键字和分号 - 当您发布片段时,请确保它是正确的代码,因为有些人(即我)会尝试编译它。

Second of all, dont use function template specialization.其次,不要使用 function 模板专业化。 If macros are evil, then they must be satan incarnation.如果宏是邪恶的,那么它们一定是撒旦的化身。 Just stick to the good old overloads.只需坚持旧的重载即可。 See here for details.有关详细信息,请参见此处

And at least - an answer.至少 - 一个答案。 You could mess around with variadic macros if all args were of the same type - for example, you could create an array inside writeInfo function and iterate over elements.如果所有args 都属于同一类型,您可能会弄乱可变参数宏 - 例如,您可以在 writeInfo function 中创建一个数组并迭代元素。 Since it's cleary not the case here you can define many variants of MACROWRITEINFO macro for different number of parameteres, using some common blocks to reduce code repetition.由于这里显然不是这种情况,您可以为不同数量的参数定义 MACROWRITEINFO 宏的许多变体,使用一些通用块来减少代码重复。 For example:例如:

#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()                \
}

Using those you can now define variants based on number of arguments.使用这些,您现在可以根据 arguments 的数量定义变体。

#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()

And so on...等等...

EDIT: Well I guess it is possible to use variadic macros here.编辑:好吧,我想可以在这里使用可变参数宏。 Take at look at this SO question .看看这个SO question It's pure madness, but you should be able to achieve what you want.这纯粹是疯狂,但你应该能够实现你想要的。

EDIT: My idea was to expand variadic arguments into array then iterate over them;编辑:我的想法是将可变参数 arguments 扩展为数组,然后遍历它们; if they were of the same type, let's say int, you could write:如果它们是相同的类型,比如说 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);

So if all your variables were of the same type you could put them in an array.因此,如果所有变量都属于同一类型,则可以将它们放入数组中。 But they are not, so it won't do.但他们不是,所以它不会做。 If you really, really want to stick to variadic arguments go to my first edit.如果您真的非常想坚持使用可变参数 arguments go 进行我的第一次编辑。

I don't think it's possible to do that with a macro.我认为用宏不可能做到这一点。 You can use variable arguments (variadic) but you can't generate code which depends on the arguments.您可以使用变量 arguments(可变参数),但不能生成依赖于 arguments 的代码。

I'd suggest you create a DSL (eg simple xml..) and generate code out of it.我建议您创建一个 DSL(例如简单的 xml..)并从中生成代码。 this is much cleaner and good practice.这是更清洁和良好的做法。

You could do this:你可以这样做:

<writeInfos>
    <writeInfo class="class1" amount="3">
        <arguments>
            <argument>arg1</argument>
            <argument>arg2</argument>
        </arguments>
    </writeInfo>
</writeInfos>

Then create source code out of this.然后从中创建源代码。 You should add this step in your build process..您应该在构建过程中添加此步骤..

But you can also define something much simpler.. you could put your MACROWRITEINFO "functions" in a text file and parse it yourself..但是你也可以定义一些更简单的东西..你可以把你的 MACROWRITEINFO “函数”放在一个文本文件中并自己解析它..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM