2015-05-21 28 views
15

为什么在下面的程序中没有注释掉行?将初始化列表传递给宏

#include <iostream> 
#include <vector> 
using namespace std; 

#define F1(a) 1 

int F2(vector<int>) { return 2; } 

int main() { 
    vector<int> v; 
    v = vector<int>{1,2,3}; 

    cout << F1(v) << endl; 
    //The following line doesn't compile. The error is: 
    //error: macro "F" passed 3 arguments, but takes just 1 
    //cout << F1(vector<int>{1,2,3}) << endl; // <- error! 
    cout << F1(vector<int>({1,2,3})) << endl; 
    cout << F1((vector<int>{1,2,3})) << endl; 

    cout << F2(v) << endl; 
    //The following line compiles fine 
    cout << F2(vector<int>{1,2,3}) << endl; 
    cout << F2(vector<int>({1,2,3})) << endl; 
    cout << F2((vector<int>{1,2,3})) << endl; 

    return 0; 
} 

回答

13

预处理不知道{}初始化。它看到了逗号,并认为这是一个新的宏观争论的开始。然后是下一个。只有括号()是它知道的事情。

[C++11: 16.3/11]:由最外部匹配圆括号限定的预处理令牌序列形成函数式宏的参数列表。列表中的各个参数由逗号预处理标记分​​隔,但匹配的内部括号之间的逗号预处理标记不会分隔参数。 [..]

+2

的[ GCC在线文档](https://gcc.gnu.o rg/onlinedocs/cpp/Macro-Arguments.html)有一个很好的例子和解释。 –

8

宏不是函数。它将输入vector<int>{1,2,3}解释为3个输入,即vector<int>{1,23}。您可以通过将其设置为(vector<int>{1,2,3})来改变这一点(就像您已经做过的那样)。

一切都在鬼臼中是一个表达式vector<int>(...)是一个(*特殊成员)函数,因此预处理器将其视为一个表达式

+1

有趣,可以发誓我已经说过了! ('矢量(...)'不是函数。) –

+0

@Light Dammit - 你快一点了:P我纠正了它。现在呢? – Otomo

+1

不过,'矢量(...)'这里不是一个函数调用。是的,我知道它看起来像你在调用构造函数。 –

3

另一个解决办法是改变你的可变参数宏

#define F1(...) 1 

或者,在更一般的情况:

#define M(a) a 

#define M(...) __VA_ARGS__