13

Betrachten einfachen Code:Überlastung Auflösung mit mehreren Funktionen und mehrere Konvertierungsoperatoren

#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); 
} 

Above Code funktioniert gut, und wie erwartet gcc, Klirren und VC++ wählt foo(char).

können Sie nun den Code wenig ändern:

#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); 
} 

Jetzt sollte diese foo(double) wählen haben, scheint aber nur VC++ mit dem Code glücklich ist, während Klirren und gcc mit dem obigen Code unglücklich sind.

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 
    ^

Kann jemand erklären, warum oben Code versagt? oder ist es ein Fehler ?.

Eine weitere Frage: Haben gcc und clang den Code der Überladungsauflösung?

+2

1: Definieren Sie "unglücklich". 2: Was passiert, wenn Sie 'foo (int)' entfernen? – Amit

+2

@Amit unglücklich bedeutet, dass Code abgelehnt wird, und wie für die Entfernung der Funktion 'foo (int)' ist es nicht Teil der Frage, Sie können es bitte selbst versuchen. –

+1

@AngelusMortis: Welche Funktion wählt VC++? – davidhigh

Antwort

4

TL; DR: Der Unterschied ist, dass im ersten Fall in Bezug auf den zweiten gegenüberliegenden, die benutzerdefinierten Konvertierungssequenzen (A -> char, A -> int) rufen die gleiche Umwandlungsfunktion (operator char). Das ermöglicht uns, die Verbindung über [over.ics.rank]/(3.3) zu lösen.


Der beste Conversion-Betreiber für bestimmte Funktionen von [over.match.best]/(1.4) ausgewählt werden (Vergleich der Konvertierungssequenzen ihrer Rückgabetypen).

Daraus ergibt sich die bessere Umwandlungsfunktion für foo(int)operator char ist durch eine Beförderung zum int gefolgt, im Gegensatz zu operator double durch einen Gleitpunkt Umwandlung gefolgt.

Betrachten wir nun beide Varianten der zweiten Überlast:

  1. Die besten ICS foo(char) ist auch über operator char (Identität besser als Floating-Point-Konvertierung).So [over.ics.rank]/(3.3) ist anwendbar:

    Benutzerdefinierte Umwandlungsfolge U1 ist eine bessere Conversion-Sequenz als eine andere benutzerdefinierte Konvertierungssequenz U2wenn sie die gleiche benutzerdefinierte Konvertierungsfunktion [...] und in jedem Fall enthalten die die zweite Standard-Umwandlungssequenz von U1 ist besser als die zweite Standard-Umwandlungssequenz von U2.

    Daher wird die Gesamtkonvertierung zu F2 als besser angesehen, und es wird ausgewählt.

  2. Die beste ICS foo(double) ist über operator double. Wir enden mit zwei Umwandlungssequenzen, die verschiedene Umwandlungsfunktionen verwenden; Nichts gilt wirklich, und wir bekommen nur eine Zweideutigkeit.

5

A -> char ist A -> char.

A -> int ist A -> char -> int (weil char zu int ist eine Förderung und so schlägt den double zu int Umsatz).

A -> double ist A -> double.

Zwei benutzerdefinierte Konvertierungssequenzen sind nur vergleichbar, wenn sie dieselbe benutzerdefinierte Konvertierungsfunktion aufweisen. Somit ist A -> char eine bessere Konvertierungssequenz als A -> int, so dass Ihr erster Fall eindeutig ist. Weder A -> int noch A -> double ist besser als die andere, so dass der zweite Fall mehrdeutig ist.

Verwandte Themen