简体   繁体   English

有没有办法在可变参数宏参数上使用C ++预处理器字符串?

[英]Is there a way to use C++ preprocessor stringification on variadic macro arguments?

My guess is the answer to this question is no, but it would be awesome if there was a way. 我的猜测是这个问题的答案是否定的,但如果有办法的话会很棒。 To clarify, assume I have the following macro: 为了澄清,假设我有以下宏:

#define MY_VARIADIC_MACRO(X...) // Does some stuff here in the macro definition

What I would like to do is somehow perform stringification on all the variables of X before passing it to a variadic function; 我想要做的是以某种方式对X的所有变量执行字符串化,然后将其传递给可变参数函数; the keyword here is before. 这里的关键字是之前的。 I realize there's no way to really access the individual arguments from within the macro definition, but is there a way to stringify all the arguments, with maybe something like the following? 我意识到没有办法真正从宏定义中访问单个参数,但是有没有办法将所有参数字符串化,可能是类似下面的内容?

#define MY_VARIADIC_MACRO(X...) some_variadic_function("some string", #X)

You can use various recursive macro techniques to do things with variadic macros. 您可以使用各种递归宏技术来处理可变参数宏。 For example, you can define a NUM_ARGS macro that counts the number of arguments to a variadic macro: 例如,您可以定义NUM_ARGS宏来计算可变参数宏的参数数量:

#define _NUM_ARGS(X100, X99, X98, X97, X96, X95, X94, X93, X92, X91, X90, X89, X88, X87, X86, X85, X84, X83, X82, X81, X80, X79, X78, X77, X76, X75, X74, X73, X72, X71, X70, X69, X68, X67, X66, X65, X64, X63, X62, X61, X60, X59, X58, X57, X56, X55, X54, X53, X52, X51, X50, X49, X48, X47, X46, X45, X44, X43, X42, X41, X40, X39, X38, X37, X36, X35, X34, X33, X32, X31, X30, X29, X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, X18, X17, X16, X15, X14, X13, X12, X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1, N, ...)   N

#define NUM_ARGS(...) _NUM_ARGS(__VA_ARGS__, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

Then with that, you can write a FOREACH macro that expands another macro for each element of a list: 然后,您可以编写一个FOREACH宏,为列表的每个元素扩展另一个宏:

#define EXPAND(X)       X
#define FIRSTARG(X, ...)    (X)
#define RESTARGS(X, ...)    (__VA_ARGS__)
#define FOREACH(MACRO, LIST)    FOREACH_(NUM_ARGS LIST, MACRO, LIST)
#define FOREACH_(N, M, LIST)    FOREACH__(N, M, LIST)
#define FOREACH__(N, M, LIST)   FOREACH_##N(M, LIST)
#define FOREACH_1(M, LIST)  M LIST
#define FOREACH_2(M, LIST)  EXPAND(M FIRSTARG LIST) FOREACH_1(M, RESTARGS LIST)
#define FOREACH_3(M, LIST)  EXPAND(M FIRSTARG LIST) FOREACH_2(M, RESTARGS LIST)
        :

Which will in turn allow you to to define your macro that stringifies each of its arguments: 这将允许您定义用于对其每个参数进行字符串化的宏:

#define STRINGIFY(X)    #X
#define MY_VARIADIC_MACRO(...)    FOREACH(STRINGIFY, (__VA_ARGS__))

Okay, I didn't mean to answer my own question here, but I've come up with a decent solution that is somewhat of a combination of Mark Wilkins answer and the example I gave in the question. 好吧,我并不打算在这里回答我自己的问题,但是我想出了一个不错的解决方案,它有点像Mark Wilkins的回答和我在问题中给出的例子。

It is possible to stringify the entire set variadic set, which then includes the delimiting commas in the string. 可以对整个集变量集进行字符串化,然后在字符串中包含分隔符。 Here's a quick example: 这是一个简单的例子:

#define MY_VARIADIC_MACRO(X...) printf(#X)

Using the above macro shows you that the entire set of arguments passed to the macro gets stringified. 使用上面的宏显示传递给宏的整个参数集得到了字符串化。

Then you can then define a function to tokenize these arguments using the delimiting comma, thereby getting the set of tokenized strings by using the variadic macro: 然后,您可以使用分隔逗号定义一个函数来标记这些参数,从而通过使用可变参数宏获取标记化字符串集:

#define MY_VARIADIC_MACRO(X...) tokenize_my_arguments(#X)

Then there's actually no longer the dependency of having the variadic macro call a variadic function and I can iterate nicely through my array of constant C strings rather than iterating through va_arg. 然后实际上不再有可变参数宏调用可变参数函数的依赖性,我可以通过我的常量C字符串数组很好地迭代,而不是通过va_arg迭代。

* New Stuff from Edit Follows * *来自编辑的新资料如下*

Per Tim's comment, here's the details of the solution. Per Tim的评论,这里是解决方案的细节。 Please forgive any errors since it was done in haste and I had to port from what I'm working on. 请原谅任何错误,因为它是在急速完成的,我不得不从我正在处理的东西移植。 Also, it's not meant to be copy/paste solution since it only outputs the stringification of the arguments to demonstrate POC, but should be sufficient enough to demonstrate the functionality. 此外,它并不意味着是复制/粘贴解决方案,因为它只输出参数的字符串来演示POC,但应足以证明其功能。

Although this solution requires some run time computation, variadic macros often times call variadic functions and requires iterating through va_args, so the iteration takes place in finding the tokens, although a bit of performance is probably sacrificed. 尽管此解决方案需要一些运行时计算,但可变参数宏通常会调用可变参数函数并需要迭代va_args,因此迭代发生在查找令牌时,尽管可能牺牲了一些性能。 However, for maintainability, versatility, and ease of implementation, this seems to be the best option at the moment: 但是,为了可维护性,多功能性和易于实现,这似乎是目前最好的选择:

#define VARIADIC_STRINGIFY(_ARGUMENTS_TO_STRINGIFY...) Variadic_Stringification_Without_Variadic_Function(#_ARGUMENTS_TO_STRINGIFY)

void Variadic_Stringification_Without_Variadic_Function (const char* _stringified_arguments)
{
    strcpy(converted_arguments, _stringified_arguments);

    for(char* token = strtok(converted_arguments, ","); token != 0x0; token = strtok(0x0, ","))
        std::cout << token << std::endl;
}

This is probably is not very close to what you are wanting, but something like the following might get you there: 这可能与你想要的并不是很接近,但是下面的内容可能会让你在那里:

#define MY_VARIADIC_MACRO(X) printf( "%s\n", #X )

Then use it like the following. 然后像下面这样使用它。 Enclose the parameters in parens so that it appears as one parameter to the macro. 将参数括在parens中,使其显示为宏的一个参数。

MY_VARIADIC_MACRO(( var1, var2, "string" )); MY_VARIADIC_MACRO((var1,var2,“string”));

You could then have the macro call some function that strips off the outer parens or possibly parses the given string. 然后你可以让宏调用一些函数来剥离外部的parens或者可能解析给定的字符串。

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

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