13

xem xét mã đơn giản:độ phân giải quá tải với nhiều chức năng và nhiều nhà khai thác chuyển đổi

#include<iostream> 

struct A { 
    operator double(){ 
     std::cout<<"Conversion function double chosen."<<std::endl; 
     return 1.1; 
    } 
    operator char(){ 
     std::cout<<"Conversion function char chosen."<<std::endl; 
     return 'a'; 
    } 
} a; 

void foo(int){} 
void foo (char){} 
int main() { 
    foo(a); 
} 

Trên đang hoạt động tốt, và như mong đợi gcc, kêu vang và VC++ chọn foo(char).

Bây giờ cho phép sửa đổi mã chút:

#include<iostream> 

struct A { 
    operator double(){ 
     std::cout<<"Conversion function double chosen."<<std::endl; 
     return 1.1; 
    } 
    operator char(){ 
     std::cout<<"Conversion function char chosen."<<std::endl; 
     return 'a'; 
    } 
} a; 

void foo(int){} 
void foo (double){} //parameter changed from char to double 
int main() { 
    foo(a); 
} 

Bây giờ này nên có chọn foo(double), nhưng dường như chỉ VC++ là hạnh phúc với mã trong khi kêu vang và gcc không hài lòng với đoạn code trên.

main.cpp:11:10: error: call of overloaded 'foo(A&)' is ambiguous 
foo(a); 
    ^
main.cpp:8:6: note: candidate: void foo(int) 
void foo(int){} 
    ^
main.cpp:9:6: note: candidate: void foo(double) 
void foo (double){} //parameter changed from char to double 
    ^

Bất cứ ai có thể giải thích lý do mã trên không thành công? hoặc là lỗi ?.

Một câu hỏi khác: Làm mã gcc và mã chia sẻ phân giải quá tải?

+2

1: Xác định "không hài lòng". 2: Điều gì xảy ra nếu bạn xóa 'foo (int)'? – Amit

+2

@Amit không hạnh phúc có nghĩa là mã bị từ chối, và như để loại bỏ các chức năng 'foo (int)', nó không phải là một phần của câu hỏi, bạn có thể thử nó cho mình xin vui lòng. –

+1

@AngelusMortis: chức năng nào VC++ chọn? – davidhigh

Trả lời

4

TL; DR: Sự khác biệt là trong trường hợp đầu tiên, như trái ngược với thứ hai, trình tự chuyển đổi người dùng định nghĩa (A -> char, A -> int) gọi hàm chuyển đổi cùng (operator char). Điều đó cho phép chúng ta phá vỡ tie qua [over.ics.rank]/(3.3).


Toán tử chuyển đổi tốt nhất cho các chức năng cụ thể được chọn bởi [over.match.best]/(1.4) (so sánh chuỗi chuyển đổi của loại trả về).

Do đó, hàm chuyển đổi tốt hơn cho foo(int)operator char, sau đó là quảng cáo tới int, thay vì operator double theo sau là chuyển đổi điểm nổi.

Bây giờ xem xét cả hai biến thể của tình trạng quá tải thứ hai:

  1. Các ICS tốt nhất để foo(char)cũng qua operator char (sắc tốt hơn so với chuyển đổi dấu chấm động).Như vậy [over.ics.rank]/(3.3) được áp dụng:

    người dùng định nghĩa chuyển đổi chuỗi U1 là một chuỗi chuyển đổi tốt hơn so với một chuỗi chuyển đổi người dùng định nghĩa U2nếu chúng chứa cùng một chức năng chuyển đổi người dùng định nghĩa [...] và trong cả hai trường hợp trình tự chuyển đổi tiêu chuẩn thứ hai của U1 tốt hơn trình tự chuyển đổi tiêu chuẩn thứ hai của U2.

    Do đó, chuyển đổi tổng thể thành F2 được coi là tốt hơn và được chọn.

  2. ICS tốt nhất để foo(double)qua operator double. Chúng tôi kết thúc với hai chuỗi chuyển đổi sử dụng các hàm chuyển đổi riêng biệt; không có gì thực sự áp dụng, và chúng tôi chỉ nhận được một sự mơ hồ.

5

A -> charA -> char.

A -> intA -> char -> int (vì char để int là một thúc đẩy và vì thế nhịp đập chuyển đổi double để int).

A -> doubleA -> double.

Hai trình tự chuyển đổi do người dùng xác định chỉ có thể so sánh nếu chúng liên quan đến cùng một hàm chuyển đổi do người dùng xác định. Do đó, A -> char là chuỗi chuyển đổi tốt hơn so với A -> int, vì vậy trường hợp đầu tiên của bạn không rõ ràng. Không phải A -> int cũng không phải A -> double là tốt hơn so với khác, vì vậy trường hợp thứ hai là mơ hồ.

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