5

Visual C++ 2012. Mã. Tôi nghĩ nó nên biên dịch; trình biên dịch không đồng ý một cách tôn trọng. Tôi đã thu hẹp yêu cầu của mình xuống:Độ phân giải quá tải không rõ ràng bất ngờ trong VC++ 2012

struct B { }; 

void foo(B* b, signed int si) { } // Overload 1 
void foo(B const* b, unsigned int ui) { } // Overload 2 

int main() 
{ 
    B b; 
    unsigned int ui; 
    foo(&b, ui); 
} 

Vì vậy, chúng tôi đã có hai ứng cử viên để giải quyết quá tải. Đối với quá tải đầu tiên, đối số đầu tiên khớp chính xác, và đối số thứ hai yêu cầu một chuyển đổi không tách rời (chưa ký để ký). Đối với quá tải thứ hai, đối số thứ hai khớp chính xác, và đối số đầu tiên yêu cầu điều chỉnh cv (vì &b là một con trỏ trỏ tới không phải là const).

Có vẻ như điều này hoàn toàn không rõ ràng. Đối với quá tải 1, đối số đầu tiên là "Đối sánh chính xác" như được xác định bởi phần tiêu chuẩn về độ phân giải quá tải, nhưng đối số thứ hai là "Chuyển đổi". Đối với quá tải 2, cả hai đối số là "Đối sánh chính xác" (chuyển đổi bằng cấp có cùng thứ hạng với danh tính). Do đó (lý do hoàn toàn không hoàn hảo của tôi), nên chọn quá tải 2, không có sự mơ hồ. Chưa:

a.cpp(12): error C2666: 'foo' : 2 overloads have similar conversions 
    a.cpp(6): could be 'void foo(const B *,unsigned int)' 
    a.cpp(5): or  'void foo(B *,int)' 
    while trying to match the argument list '(B *, unsigned int)' 
    note: qualification adjustment (const/volatile) may be causing the ambiguity 

GCC có vẻ tốt với mã, cả bằng phương ngữ mặc định và C++ 11 (cảm ơn, IDEOne!). Vì vậy, tôi kiiiiind của nghiêng để điều này lên đến một lỗi trong MSVC, nhưng (a) bạn biết những gì họ nói về những người nghĩ rằng lỗi của họ là lỗi trình biên dịch, và (b) điều này có vẻ như nó sẽ là một lỗi khá rõ ràng , loại sắp xếp sẽ gửi cờ đỏ trong quá trình kiểm tra sự phù hợp của chúng.

Đây có phải là MSVC không tuân thủ hay GCC không tuân thủ không? (Hoặc cả hai?) Có phải lý do của tôi liên quan đến âm thanh phân giải quá tải không?

+1

Tôi không biết trình biên dịch nào là đúng, nhưng là con người tôi muốn biết quá tải sẽ được sử dụng mà không cần phải định hướng dựa trên "ưu tiên" của hai loại chuyển đổi :-) – Cameron

+0

@Cameron Oh, tôi đồng ý. Trường hợp sử dụng thực tế có ý nghĩa hơn rất nhiều, và thực sự * trông * rõ ràng. – Sneftel

Trả lời

7

MSVC là chính xác.

gcc 4.9.0 nói:

cảnh báo: ISO C++ nói rằng đây là những mơ hồ, mặc dù việc chuyển đổi tồi tệ nhất đối với người đầu tiên là tốt hơn so với việc chuyển đổi tồi tệ nhất cho phần thứ hai: [kích hoạt theo mặc định]

clang 3.4.1 đồng ý rằng hai chức năng không rõ ràng.

Mặc dù B* => B*B* => B const* cả hai đều có Exact Match cấp bậc, cựu vẫn là một chuỗi chuyển đổi tốt hơn mỗi over.ics.rank/3; đây là (mỗi ví dụ) để đảm bảo rằng:

int f(const int *); 
int f(int *); 
int i; 
int j = f(&i); // calls f(int*) 

Từ over.ics.rank/3:

Chuẩn chuỗi chuyển đổi S1 là một chuỗi chuyển đổi tốt hơn so với trình tự chuyển đổi tiêu chuẩn S2 nếu [.. .]
- S1 và S2 chỉ khác nhau trong quá trình chuyển đổi tiêu chuẩn và tương ứng với các loại T1 và T2 (4.4) và chữ ký cv của loại T1 là một tập con thích hợp của chữ ký cv-qualification loại T2. [...]

Và, tất nhiên, unsigned int => unsigned int là tốt hơn unsigned int => signed int. Vì vậy, trong hai tình trạng quá tải, một trong những có một chuỗi chuyển đổi tiềm ẩn tốt hơn trên đối số đầu tiên, và khác có một chuỗi chuyển đổi tiềm ẩn tốt hơn trên đối số thứ hai. Vì vậy, chúng không thể được phân biệt trên over.match.best/1.

+0

Cảm ơn. Vậy lỗ hổng trong lý luận của tôi là gì? Dường như từ đọc của tôi về tiêu chuẩn rằng không có chuyển đổi cho quá tải 2 mà là tồi tệ hơn so với chuyển đổi tương ứng cho quá tải 1 - rằng trình biên dịch không nên thích 'B *' để 'B const *' khi so sánh quá tải. – Sneftel

+0

@Sneftel ah, nhưng nó - Tôi sẽ thêm từ ngữ chính xác. – ecatmur

+0

Yeh, chỉ tìm thấy điều đó. Có vẻ như tôi đã ngừng đọc quá sớm. Cảm ơn bạn đã đào bới. – Sneftel

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