为什么要向这个宏传递三个参数?
Why is this macro being passed three arguments?
#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 在在线编译器上编译时,我才得到一个更具描述性的错误:
error: macro "push" passed 3 arguments, but takes just 1
我想我很困惑,因为我认为 std::initializer_list 是一个结构,应该作为一个结构传递。当它抱怨将 3 个参数传递给宏时,它是通过 push({1, 2, 3}); 说的我正在做相当于 push(1, 2, 3); 的事情?这似乎 std::initializer_list 在解析宏时在预编译器阶段之前对其元素进行了一种扩展。我不明白这是为什么。此外,我尝试将其包装在另一组括号中并且有效:
push( ( {1, 2, 3} ) );
宏非常原始且受限,它们(不一定)对所使用的编程语言一无所知。
假设您有宏
#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 with compiler flags set to -E
open to check macro expansion. Example
#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 在在线编译器上编译时,我才得到一个更具描述性的错误:
error: macro "push" passed 3 arguments, but takes just 1
我想我很困惑,因为我认为 std::initializer_list 是一个结构,应该作为一个结构传递。当它抱怨将 3 个参数传递给宏时,它是通过 push({1, 2, 3}); 说的我正在做相当于 push(1, 2, 3); 的事情?这似乎 std::initializer_list 在解析宏时在预编译器阶段之前对其元素进行了一种扩展。我不明白这是为什么。此外,我尝试将其包装在另一组括号中并且有效:
push( ( {1, 2, 3} ) );
宏非常原始且受限,它们(不一定)对所使用的编程语言一无所知。
假设您有宏
#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 with compiler flags set to -E
open to check macro expansion. Example