#include <vector>
struct Foo { int a, b, c; };
int main()
{
Foo myFoo = Foo{ 1, 2, 3 };
std::vector<Foo> listOfFoos;
listOfFoos.push_back(Foo{ 1, 2, 3 });
#define push(x) listOfFoos.push_back(x)
push(Foo{ 1, 2, 3 } ); // Error
}
错误是:
> "Expected a '}'"
> "Syntax error: expected a ')' not '}'" "Syntax
> error: missing ')' before ';'"
我花了很多时间在Visual Studio上试图弄清楚发生了什么。直到我使用GCC编译在线编译器之后,我才得到更具描述性的错误:
错误:宏&#34;推&#34;传递3个参数,但只需1个
我想我很困惑,因为我认为std :: initializer_list是一个结构,应该作为一个结构传递。当它抱怨传递给宏的3个参数是通过push({1,2,3})说的;我做的相当于推(1,2,3);?这似乎是std :: initializer_list在解析宏时在预编译器阶段之前对其元素进行了一种扩展。我不明白为什么会这样。此外,我尝试将其包装在另一组括号中,它可以工作:
push( ( {1, 2, 3} ) );
答案 0 :(得分:4)
宏非常原始且有限,它们(必然)对它们所使用的编程语言一无所知。
假设你有宏
#define foo(x, y, z)
并像foo(1, 2, 3)
一样使用它。预处理器以逗号(,
)分割,并根据输入数字设置变量x
,y
和z
。在您的宏观调用push(Foo{ 1, 2, 3 } )
中,这并没有什么不同。它以逗号分隔,并将x
设置为Foo{ 1
。但是,还有两个值2
和3 }
,因此出现错误。对于预处理器来说,花括号对于并不特别,它只是另一个字母。
要通过传递所有内容,而不是采用一个参数,请将其视为va-args:
#define push(...) listOfFoos.push_back(__VA_ARGS__)
其中...
表示,如果有任何额外内容,只需将其,__VA_ARGS__
表示扩展到您额外收取的所有内容。
提示:将godbolt.org的选项卡设置为-E
以打开以检查宏扩展,总是很好。 Example