2011-06-25 75 views
36

Nhìn trên this site, mã cho thấy lời gọi vĩ mô sử dụng một dấu ngã trong ngoặc đơn:Dấu ngã (~) trong macro có nghĩa là gì?

HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~)) 
//           ^^^ 

có nghĩa là gì/làm gì? Tôi nghi ngờ nó chỉ là một cuộc tranh luận trống rỗng, nhưng tôi không chắc chắn. Nó có thể cụ thể cho C (99) như __VA_ARGS__ là cụ thể cho C99 và tồn tại trong C + +?

+1

đó là đối số giả – Anycorn

+1

~ là phần bổ sung bitwise, như bạn có thể đã biết. Có vẻ như chỉ là một trình giữ chỗ cho tôi. Tôi không nghĩ nó có ý nghĩa đặc biệt nào cả. –

Trả lời

28

Trên trang giới thiệu Boost.Preprocessor, một ví dụ được đưa ra trong A.4.1.1 ngang Lặp

#define TINY_print(z, n, data) data 

#define TINY_size(z, n, unused)         \ 
    template <BOOST_PP_ENUM_PARAMS(n, class T)>     \ 
    struct tiny_size<            \ 
     BOOST_PP_ENUM_PARAMS(n,T)         \ 
     BOOST_PP_COMMA_IF(n)          \ 
     BOOST_PP_ENUM(           \ 
      BOOST_PP_SUB(TINY_MAX_SIZE,n), TINY_print, none)  \ 
    >                \ 
    : mpl::int_<n> {}; 

BOOST_PP_REPEAT(TINY_MAX_SIZE, TINY_size, ~) // Oh! a tilde! 

#undef TINY_size 
#undef TINY_print 

Giải thích được cung cấp dưới đây:

Quá trình sinh mã được khởi động bằng cách gọi BOOST_PP_REPEAT, một số bậc cao hơn nhiều lần gọi macro được đặt tên theo đối số thứ hai của nó (TINY_size). Đối số đầu tiên xác định số lượng lời gọi lặp lại, và đối số thứ ba có thể là bất kỳ dữ liệu nào; nó được truyền trên không thay đổi cho macro đang được gọi. Trong trường hợp này, TINY_size không sử dụng dữ liệu đó, do đó, lựa chọn để vượt qua ~ là tùy ý. [5]

(tôi nhấn mạnh)

Và đó là lưu ý:

[5]~ không phải là một lựa chọn hoàn toàn tùy ý. Cả hai @$ có thể là lựa chọn tốt, ngoại trừ việc chúng về mặt kỹ thuật không phải là một phần của bộ ký tự cơ bản mà việc triển khai C++ được yêu cầu để hỗ trợ. Một số nhận dạng như bị bỏ qua có thể bị mở rộng macro, dẫn đến kết quả không mong muốn.

Dấu ngã, do đó, chỉ đơn giản là trình giữ chỗ vì cần có đối số nhưng không cần thiết. Vì bất kỳ định danh do người dùng định nghĩa wannabe có thể được mở rộng, bạn cần phải sử dụng một cái gì đó khác.

Nó chỉ ra rằng ~ là khá nhiều không sử dụng (phủ định nhị phân không phải là thường được gọi là) so với + hoặc - ví dụ, vì vậy có rất ít cơ hội của sự nhầm lẫn.Khi bạn đã giải quyết vấn đề này, hãy sử dụng nó một cách nhất quán sẽ mang lại cho nó mới ý nghĩa đối với dấu ngã; như sử dụng operator<<operator>> để phát trực tuyến dữ liệu đã trở thành thành ngữ C++.

+0

Cảm ơn, đó là một tìm kiếm tốt và chính xác những gì tôi cần. :) – Xeo

+0

+1 của tôi, Đó là một tìm kiếm rất tốt! Tôi không thể tìm thấy bất kỳ tài liệu tham khảo tiêu chuẩn cho nó & đã đấu tranh để hiểu nó triệt để. Câu trả lời của bạn sắp xếp nó ra độc đáo. –

+0

Làm thế nào chính xác có thể mở rộng vĩ mô dẫn đến kết quả bất ngờ, xem xét các đối số (và do đó, đối số mở rộng vĩ mô) không xuất hiện trong việc mở rộng của TINY_size? – Random832

3

Các đối số được thử nghiệm được đặt giữa vĩ mô và ngoặc của nó, macro chỉ gây nên nếu đối số là rỗng:

_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~) 

Chú ý: Thực ra rất liên kết bạn được đăng khẳng định nó. Tôi sẽ kiểm tra một tham chiếu đến điều này trong tiêu chuẩn.

+0

Trên ghi chú của bạn: Vâng, sau khi đọc lại nó một vài lần sau khi đăng câu hỏi nó đến với tôi ... Đây không phải là lần đầu tiên tôi hỏi một câu hỏi và một vài phút sau đó giải pháp đến tâm trí ... :(Ngoài ra, câu đầu tiên của bạn bằng cách nào đó dường như không liên quan trực tiếp đến câu hỏi – Xeo

+0

@Xeo: Xin lỗi, tôi e rằng tôi không hiểu ngữ cảnh đủ để đăng câu trả lời phức tạp, có kết cục lỏng lẻo là tại sao chỉ có ' ~ 'và tôi tiếp tục tàn phá tiêu chuẩn lâu dài mà không thành công. Tuyệt vời, tìm thấy bởi @Matthieu M. mặc dù, tôi có thể ngủ một cách hòa bình! –

+0

Cảm ơn vì sự phiền toái của bạn. :) – Xeo

4

~ không làm gì cả. Hầu như bất kỳ nội dung nào bên trong các dấu ngoặc đơn đó sẽ hoạt động giống nhau.

Lynchpin của mẹo này là để kiểm tra xem _TRIGGER_PARENTHESIS_ có nằm cạnh (~) khi mở rộng _TRIGGER_PARENTHESIS_ __VA_ARGS__ (~) hay không. Dù bằng cách nào, HAS_COMMA(...) mở rộng đối số của nó thành 0 hoặc 1.

+0

Tôi tự hỏi làm thế nào điều này sẽ diễn ra với một đối số đó là chính macro .. '_TRIGGER_PARENTHESIS_ MYMACRO (~)'. – Xeo

+0

tại sao anh ta sử dụng '(~)' chứ không phải '(+)' hay cái gì khác? –

+0

@Johannes: có một lý do được cung cấp trên trang Giới thiệu Boost.Preprocessor, tôi đã trích dẫn bên dưới. Mục tiêu là sử dụng mã thông báo tiền xử lý hợp lệ nhưng hiếm. –

Các vấn đề liên quan