是否可以传递一个括号括起来的初始化程序作为宏参数? [英] Is it possible to pass a brace-enclosed initializer as a macro parameter?

查看:257
本文介绍了是否可以传递一个括号括起来的初始化程序作为宏参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,我这样调用:

I have a function that I call like this:

literal<long[2]>({1, 2});

我想写一个扩展到此语句的宏,例如:

I want to write a macro that expands to this statement, e.g.:

MYMACRO(long[2], {1, 2})

$ b不幸的是,预处理器不知道括号匹配,所以它看到三个参数(第二个和第三个是 {1 2} )。

Unfortunately, the preprocessor is not aware of brace-matching so it sees three arguments (the second and third are {1 and 2}, respectively).

这是预处理器的已知限制,最简单的解决方案是添加额外的括号

This is a known limitation of the preprocessor, and the simplest solution is often to add extra parentheses, if possible, in the macro invocation.

但是,在这种情况下,将括号括起来的初始值设置放在括号中似乎改变了其含义:

But, in this case, placing the brace-enclosed initializer inside parentheses appears to change its meaning:

literal<long[2]>(({1, 2}));

(g++ 4.8) error: left operand of comma operator has no effect [-Werror=unused-value]

这是一个GCC错误还是正确的设计?有没有办法完成我想要的?

Is this a GCC bug or correct by design? Is there any way to accomplish what I want?

我可能应该在原始问题的措辞。预处理器没有永远改变(即使可变宏是长期以来的GCC扩展)。在这种情况下的实际解决方法是有用的,但它们也是非常知名的,而不是我想要的点。

I probably should have been more clear in the phrasing of the original questions. The preprocessor hasn't changed in forever (even variadic macros have been a GCC extension for a long time). The practical workarounds in this case are useful, but they're also very well known and not to the point I want to get at.

我真的想知道是否有什么被添加到C ++ 11以专门解决这个问题(或者是一个监督?)。

I really want to know whether anything was added to C++11 to specifically address this issue (or was it an oversight?). The quirky handling of braces in macro invocations seems like a much bigger issue now, given the greatly expanded use of brace-enclosed lists throughout the language.

我特别懊恼的是,在宏调用中,大括号的处理似乎是一个更大的问题。通过在括号括起来的初始化器列表上放置括号会改变用作函数参数时解析的方式。有没有任何其他参数的函数调用,不能括号?在编写将参数传递给函数的宏时,它看起来像是特殊情况。

I'm especially annoyed by the fact that putting parentheses around a brace-enclosed initializer list changes the way it's parsed when used as a function parameter. Is there any other parameter to a function invocation that cannot be parenthesized? It seems like special-case hell when writing macros that pass parameters to functions.

我真的希望有人能够指出这是一个GCC错误,

I'm really hoping somebody can point out that this is a GCC bug, or explain why putting parentheses around a brace-enclosed initializer list must change its meaning.

推荐答案

您可以使用

#define MYMACRO(T,...) literal<T>(__VA_ARGS__);

如果您有更多参数,可以使用间接:

In case you have more parameters, you can use an indirection:

#define UNWRAP(...) __VA_ARGS__
#define MYMACRO(T,A) literal<T>(UNWRAP A);

现在您可以使用

MYMACRO( long[2], ({1, 2}) )



< hr>

更新的答案

您也可以根据需要更换大括号调用具有圆括号的宏:

You could also, if you like, replace the curly brackets in the invocation of the macro with the round brackets:

#define BRACED_INIT_LIST(...) {__VA_ARGS__}
#define MYMACRO(T,A) literal<T>(BRACED_INIT_LIST A);

并致电

MYMACRO( long[2], (1, 2) )

与典型的宏调用风格一致。

which is IMHO consistent with typical macro-invocation-styles.

在你的其他问题上的一些话:预处理器不了解语言(C,C ++,C ++ 11)不应该关心符号的特殊意义。它跟踪圆括号,但几乎所有的东西只是令牌。

Some words on your other questions: The preprocessor knows nothing about the language (C, C++, C++11) and hence should not care about the special meaning of symbols. It is tracking round brackets, but almost everything else is just tokens.

我也认为这不是标准委员会的监督,因为重点应该是使用在大多数情况下预处理器是多余的。您是否考虑过其他(非宏)技术来实现 MYMACRO ?另外,剩下的使用情况(如上所示)的解决方法当然是可能的。

I also think it's not an oversight from the standard committee as the focus should be on making the use of the preprocessor superfluous for most cases. Have you considered other (non-macro) techniques to implement MYMACRO? Also, work-arounds for the remaining use-cases (as shown above) are certainly possible.

最后,它肯定不是GCC中的错误,因为编译器只是实现标准是什么。

Finally, it is certainly not a bug in GCC as the compiler simply implements what the standard says.

这篇关于是否可以传递一个括号括起来的初始化程序作为宏参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆