将初始化列表传递给宏

Bar*_*uch 17 c++ c-preprocessor c++11

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

#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;
}
Run Code Online (Sandbox Code Playgroud)

Lig*_*ica 14

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

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

  • [GCC在线文档](https://gcc.gnu.org/onlinedocs/cpp/Macro-Arguments.html)有一个很好的例子和解释. (2认同)

Oto*_*omo 9

宏不是一个功能.它解释你的输入vector<int>{1,2,3}为输入3个,它们是vector<int>{1,23}.你可以通过使它成为一个表达式来改变它(vector<int>{1,2,3})(就像你已经做过的那样).

在parantheses的一切都是一种表达 并且vector<int>(...)是(*特殊成员 - )函数,因此预处理器将其视为一个表达式.


Jar*_*d42 5

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

#define F1(...) 1
Run Code Online (Sandbox Code Playgroud)

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

#define M(a) a
Run Code Online (Sandbox Code Playgroud)

进入

#define M(...) __VA_ARGS__
Run Code Online (Sandbox Code Playgroud)