2009-10-20 31 views
9

Đây là một cái gì đó tôi quan sát thấy trên các trình biên dịch khác nhau. Dường như có lỗi trình biên dịch.Tại sao biểu thức tham số mẫu không kiểu xử lý không nhất quán giữa các trình biên dịch?

template <int I> 
struct X 
{ }; 

int main(void) 
{ 
    X<(16 > 1)> a;  // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1 
    X<(int(16) > 1)> b; // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1 
    X<(16 >> 1)> c;  // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1 
    X<(int(16) >> 1)> d; // Fails on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1 

    X<16 > 1> e;   // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1 
    X<int(16) > 1> f; // Fails on vc9, fails on g++ 4.1.2, fails on Comeau 4.3.10.1 
    X<16 >> 1> g;  // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1 
    X<int(16) >> 1> h; // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1 
} 

Tại sao sự không nhất quán đó? Những gì được cho phép/không được phép theo tiêu chuẩn? Hành vi này cũng chịu trách nhiệm về lỗi cú pháp khi sử dụng BOOST_AUTO trên vc9. Dường như với tôi rằng Comeau đang làm đúng công việc bằng cách từ chối tất cả các biểu thức mà không có dấu ngoặc đơn.

+5

Tôi không nghĩ rằng nó có bất cứ điều gì để làm với các mẫu là không loại, mà là vì nó sử dụng ký tự '>' bên trong khuôn mẫu. – Marcin

+0

Bạn nói đúng Marcin, tôi đã thấy hành vi không nhất quán này với các toán tử quá tải '>' và '>>' của các lớp do người dùng định nghĩa. – Sumant

+2

Bởi vì điều này sẽ là một cấu trúc hiếm khi được sử dụng và do đó ít có khả năng được kiểm tra. Và bạn sẽ rất tức giận khi sử dụng chúng trong mã thực. Nhưng nó là giá trị trình này như là bài kiểm tra cho nhà sản xuất trình biên dịch để họ có thể thêm nó vào bộ thử nghiệm của họ những điều điên rồ người làm. –

Trả lời

8

Các quy tắc như sau cho C++ 03:

Sau khi tra cứu tên (3.4) thấy rằng một tên là một mẫu tên tuổi, nếu tên này được theo sau là một <, các < luôn là được lấy làm khởi đầu của một danh sách-đối số-danh sách và không bao giờ là một tên theo sau bởi toán tử nhỏ hơn. Khi phân tích cú pháp mẫu-id, số đầu tiên không lồng nhau > [foot-note: A > bao quanh id loại của dynamic_cast, static_cast, reinterpret_cast hoặc const_cast hoặc bao quanh mẫu-đối số của id mẫu tiếp theo, được coi là lồng nhau cho mục đích của mô tả này. ] được lấy như là kết thúc của template-argument-list chứ không phải là toán tử lớn hơn.

Vì vậy, kết quả là:

X<(16 > 1)> a;  // works 
    X<(int(16) > 1)> b; // works 
    X<(16 >> 1)> c;  // works 
    X<(int(16) >> 1)> d; // works 

    X<16 > 1> e;   // fails 
    X<int(16) > 1> f; // fails 
    X<16 >> 1> g;  // works (">>" is not a ">" token) 
    X<int(16) >> 1> h; // works (">>" is not a ">" token). 

Tuy nhiên, trong C++ 0x sau đây là các quy tắc

Sau nds tra cứu tên (3.4) fi rằng một tên là một template- tên, hoặc rằng một toán tử-function-id đề cập đến một tập hợp các chức năng quá tải bất kỳ thành viên trong đó là một mẫu chức năng, nếu điều này được theo sau bởi một <, các < luôn luôn được thực hiện như dấu phân cách của một mẫu-đối số-danh sách và không bao giờ là hoạt động ít hơn hoặc là. Khi phân tích cú pháp mẫu-đối số-danh sách, đầu tiên không lồng nhau> [foot-note: A > bao quanh id loại của dynamic_cast, static_cast, reinterpret_cast hoặc const_cast hoặc bao quanh mẫu-đối số của mẫu tiếp theo- id, được coi là lồng nhau cho mục đích của mô tả này.] được lấy làm dấu phân tách kết thúc chứ không phải là toán tử lớn hơn. Tương tự, đầu tiên không được lồng nhau >> được coi là hai mã thông báo > liên tiếp nhưng riêng biệt, đầu tiên được lấy làm kết thúc của mẫu-đối số-danh sách và hoàn thành mẫu-id.

Ta được kết quả

X<(16 > 1)> a;  // works 
    X<(int(16) > 1)> b; // works 
    X<(16 >> 1)> c;  // works 
    X<(int(16) >> 1)> d; // works 

    X<16 > 1> e;   // fails 
    X<int(16) > 1> f; // fails 
    X<16 >> 1> g;  // fails (">>" translated to "> >") 
    X<int(16) >> 1> h; // fails (">>" translated to "> >") 

Hãy chắc chắn để vô hiệu hóa C++ 0x chế độ trong comeau khi kiểm tra

+0

Câu trả lời hay! Trên Comeau, với C++ 0x vô hiệu hóa, kết quả là như mô tả ở trên (6 công việc, 2 thất bại). – Sumant

+0

Bạn luôn có thể đếm trên litb để thực hiện nghiên cứu :) – Marcin

2

Theo Stroustrup: "Không lồng nhau đầu tiên> chấm dứt danh sách đối số mẫu. Nếu cần lớn hơn, phải sử dụng dấu ngoặc đơn".

Do đó, các trình biên dịch chịu đựng bộ biểu thức thứ hai làm như vậy không chính xác; trình biên dịch không thành công trên X<(int(16) >> 1)> d; là lỗi.

+1

đó có nghĩa là trình biên dịch thất bại trên X <16 >> 1> cũng bị lỗi, vì >> không phải là hai> (nổi tiếng lồng nhau phiền toái mẫu) – falstro

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