2015-05-21 22 views
15

Tại sao dòng nhận xét không được đưa ra trong chương trình biên dịch sau?Chuyển danh sách khởi tạo sang macro

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

Trả lời

13

Bộ tiền xử lý không biết về {} khởi tạo. Nó nhìn thấy dấu phẩy và nghĩ rằng đó là sự khởi đầu của một đối số macro mới. Và sau đó tiếp theo. Chỉ các dấu ngoặc đơn () là những thứ mà nó biết.

[C++11: 16.3/11]: Chuỗi mã tiền xử lý được bao quanh bởi dấu ngoặc đơn phù hợp nhất bên ngoài tạo danh sách đối số cho macro giống như hàm. Các đối số riêng lẻ trong danh sách được phân cách bằng mã thông báo tiền xử lý bằng dấu phẩy, nhưng mã thông báo tiền xử lý dấu phẩy giữa các dấu ngoặc đơn bên trong khớp nhau không phân tách các đối số riêng lẻ. [..]

+2

Các [ Tài liệu trực tuyến GCC] (https: //gcc.gnu.o rg/onlinedocs/cpp/Macro-Arguments.html) có một ví dụ và giải thích tốt đẹp. –

8

Macro không phải là hàm. Nó diễn giải đầu vào của bạn vector<int>{1,2,3} làm 3 đầu vào, là vector<int>{1, 23}. Bạn có thể thay đổi điều này bằng cách biến nó thành biểu thức (vector<int>{1,2,3}) (như bạn đã làm).

Mọi thứ trong các dấu ngoặc đơn là biểu thức vector<int>(...) là hàm (* thành viên đặc biệt) để bộ tiền xử lý coi nó là một biểu thức.

+1

Hài hước, có thể thề tôi đã nói điều đó !! ('vector (...)' không phải là một hàm.) –

+0

@Light Dammit - bạn đã nhanh hơn một chút: P Tôi đã sửa nó. Có phải bây giờ không? – Otomo

+1

Tuy nhiên, 'vector (...)' ở đây là _not_ một cuộc gọi hàm. Vâng, tôi biết có vẻ như bạn đang gọi nhà xây dựng. –

3

workaround khác là chuyển đổi của bạn vĩ mô thành một variadic vĩ mô

#define F1(...) 1 

Hoặc, trong một trường hợp tổng quát hơn:

#define M(a) a 

vào

#define M(...) __VA_ARGS__ 
Các vấn đề liên quan