TL; DR
Các dấu ngoặc đơn thay đổi ý nghĩa của chương trình C++ trong các ngữ cảnh sau:
ngăn chặn tra cứu tên phụ thuộc đối số
cho phép toán tử dấu phẩy trong ngữ cảnh danh sách
độ phân giải mơ hồ của phân tích cú pháp
khấu trừ tham chiếu trong biểu thức decltype
ngăn ngừa lỗi macro tiền xử lý
Ngăn chặn tra cứu tên phụ thuộc đối số
Như được nêu chi tiết trong Phụ lục A của Tiêu chuẩn, một post-fix expression có dạng (expression) là một primary expression, nhưng không phải là id-expression, và do đó không phải là unqualified-id. Điều này có nghĩa là việc tra cứu tên phụ thuộc đối số bị ngăn chặn trong các lệnh gọi hàm có dạng (fun)(arg) so với dạng thông thường fun(arg).
3.4.2 Tra cứu tên phụ thuộc đối số [basic.lookup.argdep]
1 Khi biểu thức postfix trong lệnh gọi hàm (5.2.2) là id không đủ tiêu chuẩn , các không gian tên khác không được xem xét trong quá trình tra cứu không đủ tiêu chuẩn thông thường (3.4 .1) có thể được tìm kiếm và trong các không gian tên đó, có thể tìm thấy hàm bạn bè phạm vi không gian tên hoặc khai báo mẫu hàm (11.3). Những sửa đổi đối với tìm kiếm này phụ thuộc vào các loại đối số (và đối với đối số mẫu khuôn mẫu, không gian tên của đối số mẫu). [ Thí dụ:
namespace N { struct S { }; void f(S); } void g() { N::S s; f(s);Kích hoạt toán tử dấu phẩy trong ngữ cảnh danh sách
Toán tử dấu phẩy có một ý nghĩa đặc biệt trong hầu hết các bối cảnh giống như danh sách (đối số hàm và mẫu, danh sách khởi tạo, v.v.). Dấu ngoặc đơn của biểu mẫu a, (b, c), d trong các ngữ cảnh như vậy có thể cho phép toán tử dấu phẩy so với biểu mẫu a, b, c, d thông thường mà toán tử dấu phẩy không áp dụng.
Toán tử dấu phẩy 5.18 [expr.comma]
2 Trong các ngữ cảnh trong đó dấu phẩy được cho một ý nghĩa đặc biệt, [Ví dụ: trong danh sách các đối số cho hàm (5.2.2) và danh sách các công cụ khởi tạo (8.5) Ví dụ về sự thay đổi] toán tử dấu phẩy như được mô tả trong Khoản 5 chỉ có thể xuất hiện trong ngoặc đơn. [ Thí dụ:
có ba đối số, đối số thứ hai có giá trị 5. Ví dụ về biểu tượng]
Độ phân giải mơ hồ của các phân tích cú pháp
Khả năng tương thích ngược với C và cú pháp khai báo hàm phức tạp của nó có thể dẫn đến sự mơ hồ phân tích cú pháp đáng ngạc nhiên, được gọi là phân tích cú pháp. Về cơ bản, bất cứ điều gì có thể được phân tích cú pháp dưới dạng khai báo sẽ được phân tích cú pháp thành một , ngay cả khi một phân tích cạnh tranh cũng sẽ được áp dụng.
6.8 Độ phân giải mơ hồ [stmt.ambig]
8.2 Độ phân giải mơ hồ [dcl.ambig.res]
1 Sự mơ hồ phát sinh từ sự giống nhau giữa kiểu truyền hàm và khai báo được đề cập trong 6.8 cũng có thể xảy ra trong bối cảnh khai báo . Trong ngữ cảnh đó, sự lựa chọn nằm giữa một khai báo hàm với một tập các dấu ngoặc thừa dự phòng xung quanh một tên tham số và một khai báo đối tượng với kiểu kiểu hàm làm trình khởi tạo. Cũng như đối với sự mơ hồ được đề cập trong 6.8, độ phân giải là xem xét bất kỳ cấu trúc nào có thể có thể là khai báo một khai báo . [Lưu ý: Một khai báo có thể được định nghĩa rõ ràng bằng cách sử dụng kiểu không có chức năng, bởi an = để chỉ khởi tạo hoặc bằng cách loại bỏ dấu ngoặc thừa xung quanh tên tham số. Ghi chú của người phụ nữ] [Ví dụ:
struct S { S(int); }; void foo(double a) { S w(int(a));Một ví dụ nổi tiếng về điều này là Parse Bực mình nhất , một cái tên được Scott Meyers phổ biến trong Mục 6 của STL hiệu quả cuốn sách:
Đặt dấu ngoặc đơn bổ sung xung quanh đối số chức năng đầu tiên (dấu ngoặc đơn xung quanh đối số thứ hai là bất hợp pháp) sẽ giải quyết sự mơ hồ
C++ 11 có cú pháp khởi tạo cú pháp cho phép thực hiện các vấn đề phân tích cú pháp như vậy trong nhiều ngữ cảnh.
Khấu trừ tham chiếu trong biểu thức decltype
Ngược lại với auto loại trừ, decltype cho phép tính tham chiếu (tham chiếu giá trị và giá trị) được suy ra. Các quy tắc phân biệt giữa decltype(e) và decltype((e)) biểu thức:
7.1.6.2 Trình xác định loại đơn giản [dcl.type.simple]
4 Đối với một biểu thức e, loại được biểu thị bởi decltype(e) được định nghĩa như sau:
– if e là biểu thức id chưa được mã hóa hoặc quyền truy cập thành viên lớp không được mã hóa (5.2.5), decltype(e) là loại thực thể được đặt tên bởi e. Nếu không có thực thể đó hoặc nếu e đặt tên cho một tập hợp các hàm bị quá tải, chương trình sẽ không được định dạng;
– nếu không, nếu e là một giá trị, decltype(e) là T&, trong đó T là loại e;
– nếu không, decltype(e) là loại e.
Toán hạng của bộ xác định dectype là toán hạng không được đánh giá (Khoản 5). [ Thí dụ:
decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str; }Cái đầu tiên trả về string, cái thứ hai trả về string &, là tham chiếu đến biến cục bộ str.
sử dụng dấu ngoặc đơn xung quanh các tham số macro bên trong định nghĩa macro #define TIMES(A, B) (A) * (B); để tránh quyền ưu tiên toán tử không mong muốn (ví dụ: trong TIMES(1 + 2, 2 + 1) mang lại 9 nhưng sẽ mang lại 6 mà không có dấu ngoặc đơn xung quanh (A) và (B)
sử dụng dấu ngoặc đơn xung quanh một chức năng để bảo vệ chống lại việc mở rộng macro trong các tiêu đề được bao gồm: (min)(a, b) (với tác dụng phụ không mong muốn là cũng vô hiệu hóa ADL)