将初始化列表传递给宏

时间:2015-05-21 11:16:16

标签: c++ c++11 c-preprocessor

为什么以下程序中的注释掉的行没有编译?

#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;
}

3 个答案:

答案 0 :(得分:14)

预处理器不知道{}初始化。它看到逗号并认为这是一个新的宏参数的开始。然后是下一个。只有括号()是它所知道的东西。

  

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

答案 1 :(得分:9)

宏不是一个功能。它会将您的输入vector<int>{1,2,3}解释为3个输入,即vector<int>{123}。您可以通过将其设为表达式(vector<int>{1,2,3})(就像您已经做过的那样)来更改它。

parantheses中的所有内容都是表达式,而vector<int>(...)是一个(*特殊成员)函数,因此预处理器将其视为一个表达式

答案 2 :(得分:3)

另一种解决方法是将转换为可变参数宏

#define F1(...) 1

或者,在更一般的情况下:

#define M(a) a

#define M(...) __VA_ARGS__