我刚刚发现在将参数传递给宏时,不能总是使用大括号初始化。当ASSERT()宏无法编译时,我发现了这一点。但是,以下示例说明了该问题:
#include <iostream>
#include <string>
using namespace std;
#define PRINT_SIZE( f ) cout << "Size=" << (f).size() << endl;
int main()
{
PRINT_SIZE( string("ABC") ); // OK, prints: "Size=3"
PRINT_SIZE( string{"ABC"} ); // OK, prints: "Size=3"
PRINT_SIZE( string("ABCDEF",3) ); // OK, prints: "Size=3"
PRINT_SIZE( string{"ABCDEF",3} ); // Error: macro 'PRINT_SIZE' passed 2 arguments, but takes just 1
return 0;
}
是否有理由不能使大括号初始化使用宏?
修改
我发现你也可以使用一个可变参数宏,这完全解决了这个问题:
#include <iostream>
#include <string>
using namespace std;
#define PRINT_SIZE( ... ) cout << "Size=" << (__VA_ARGS__).size() << endl;
int main()
{
PRINT_SIZE( string("ABC") ); // OK, prints: "Size=3"
PRINT_SIZE( string{"ABC"} ); // OK, prints: "Size=3"
PRINT_SIZE( string("ABCDEF",3) ); // OK, prints: "Size=3"
PRINT_SIZE( string{"ABCDEF",3} ); // OK, prints: "Size=3"
return 0;
}
答案 0 :(得分:13)
该列表分为几个宏参数。当你写
PRINT_SIZE( string{"ABCDEF",3} );
这会尝试使用两个参数展开宏PRINT_SIZE
,其中一个string{"ABCDEF"
和一个3}
失败。在许多情况下(包括你的)可以通过添加另一对括号来解决这个问题:
PRINT_SIZE( (string{"ABCDEF",3}) );
这些括号阻止了参数的拆分,因此PRINT_SIZE
扩展为一个参数(string{"ABCDEF",3})
(注意括号是参数的一部分)。
答案 1 :(得分:7)
是的,有一个原因:预处理器不知道大括号。它只尊重字符串文字和括号,对其他C / C ++语言结构它是无知的。就这样,电话
PRINT_SIZE( string{"ABCDEF",3} );
被解析为具有两个参数string{"ABCDEF"
和3}
的宏调用。由于宏PRINT_SIZE()
只需要一个参数,因此预处理器会退出。请注意,此时甚至没有调用C ++编译器!
答案 2 :(得分:0)
这个怎么样?
#define SOME_BRACE \
{ \
6, 8, 1, 3, 7, \
1, 4, 2, 0, 9 \
}
#define BRACE_SIZE(brace) (sizeof((int[]) SOME_BRACE) / sizeof(int))
int main(int argc, char *argv[])
{
int array[BRACE_SIZE(SOME_BRACE)] = SOME_BRACE, i, s;
for (i = 0, s = 0; i < BRACE_SIZE(SOME_BRACE); i++) {
s = s + array[i];
}
/* 41 is expected */
return s;
}