将初始化列表传递给宏

问题描述 投票:0回答:3

为什么下面程序中注释掉的行无法编译?

#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;
}
c++ c++11 c-preprocessor
3个回答
21
投票

预处理器不知道

{}
初始化。它看到逗号并认为这是新宏参数的开始。然后是下一张。只有括号
()
是它所知道的内容。

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


15
投票

解决方法是将您的 MACRO 转换为 可变 MACRO

#define F1(...) 1

或者在更一般的情况下;转:

#define M(a) a

进入这个:

#define M(...) __VA_ARGS__

14
投票

宏不是函数。它将您的输入

vector<int>{1,2,3}
解释为 3 个输入,分别是
vector<int>{1
2
3}
。您可以通过将其设为表达式来更改此设置
(vector<int>{1,2,3})
(就像您已经所做的那样)。

括号中的所有内容都是一个表达式 并且

vector<int>(...)
是一个(*特殊成员-)函数,因此预处理器将其视为一个表达式。

© www.soinside.com 2019 - 2024. All rights reserved.