2015-12-06 15 views
8
#include <iostream> 
using namespace std; 

struct CL2 
{ 
    CL2(){} 
    CL2(const CL2&){} 
}; 

CL2 cl2; 

struct CL1 
{ 
    CL1(){} 
    operator CL2&(){cout<<"operator CL2&"; return cl2;} 
    operator const CL2&(){cout<<"operator const CL2&"; return cl2;} 
}; 

CL1 cl1; 

int main() 
{ 
    CL1 cl1; 
    CL2 cl2 (cl1); 
} 

Zarówno dzyń i gcc dają niejednoznaczne operatora konwersji, ale Visual Studio kompiluje ok i drukuje "const operator CL2 &". Jak musi być zgodna z normą?
Tak jak nieoczekiwanie, konwersja CL1 do const CL2 & odbywa się w kontekście inicjowania kopii (jako część bezpośredniej inicjalizacji obiektu cl2). Ja widać n4296 projekt [over.match.copy]odniesienia wiązania poprzez niejednoznaczną operatora konwersji

Zakładając, że „CV1 T” jest typ obiektu zainicjowany z T typu klasy funkcje kandydujące są wybrane jako:
- Konwertujące konstruktory (12.3.1) z T są kandydatami funkcji .
- Kiedy typem wyrażenia inicjalizującego jest klasa "cv S", rozważane są nie-jawne funkcje konwersji S i jej klas podstawowych . Podczas inicjowania tymczasowego, który ma zostać powiązany, do pierwszego parametru konstruktora, którego parametrem jest typ "odniesienie do potencjalnie kwalifikowanego cv T", a konstruktor jest nazywany z pojedynczym argumentem w kontekście bezpośredniej inicjalizacji obiekt typu "cv2 T", jawne funkcje konwersji są również rozważane jako . Te, które nie są ukryte w S i dają typ, którego nienaalikowana wersja cv jest tego samego typu co T lub jest pochodną klasy , są kandydatami. Funkcje konwersji, które zwracają "odniesienie do X" zwracanych wartości lub x wartości, w zależności od typu odniesienia , typu X, a zatem są uważane za zapewniające X dla tego procesu wyboru kandydatów w ramach procesu .

tj. oba operatory konwersji są uważane za powrót CL2 i const CL2 (nie tylko CL2 bez const) i pozostaje do rozwiązania, która konwersja jest lepsza: CL2 -> const CL2 & lub const CL2 -> const CL2 &. Drugi przypadek wydaje się bardziej odpowiedni. Czy w tym kontekście należy rozważyć lepszą konwersję kwalifikacji? A może oba przypadki to konwersja tożsamości? Nie mogłem znaleźć go w standardzie

+0

Co dziwne Visual Studio * robi * kompiluje twój kod. Ale * IntelliSense * narzeka na zadeklarowanie drugiego obiektu. O ile rozumiem, twój problem nie jest taki, jak ci się wydaje. Kompilator nie wie, którą funkcję operatora konwersji wywołać, ponieważ nie można przeciążać w oparciu o typ powrotu, ale można przeciążać na podstawie stałej funkcji. Wypróbuj 'operator const CL2 &() const {cout <<" operator const CL2 & "; return cl2; } ' – DeiDei

Odpowiedz

4

Ponieważ oba operatory konwersji mają identyczne podpisy, jedynym sposobem, w jaki można je preferować, jest zastosowanie [over.match.best]/(1.4) ...

- kontekst jest inicjalizacją przez konwersję zdefiniowaną przez użytkownika (patrz 8.5, 13.3.1.5 i 13.3.1.6) oraz standardową sekwencją konwersji z typu zwrotu z F1 do typu docelowego (tj. Typ zainicjowana jednostka ) jest lepszą sekwencją konwersji niż standardowa sekwencja konwersji z typu powrotu F2 do typ miejsca docelowego.

... lub (1.5):

- kontekst jest inicjalizacja pomocą funkcji konwersji, do bezpośredniego wiązania odniesienia (13.3.1.6), z odniesieniem do działania typu [...]

Oczywiście, nie ma tu zastosowania, stąd dwuznaczność.Możliwy sposób rozróżnienia:

operator CL2&(); 
operator const CL2&() const; 

Demo; W tym przypadku początkowa standardowa sekwencja konwersji argumentu obiektu niejawnego jest lepsza, jak w [over.ics.rank]/(3.2.6), która jest decydująca dla [over.match.best]/(1.3).

+0

Dzięki, ale nie rozumiem, dlaczego mają identyczne podpisy (biorąc pod uwagę" const ")? I dlaczego w [over.match.copy] zapisano "odniesienie do X", ale nie "odniesienie do cv X" (i X wyprowadzono jako "CL2", ale nie jako "const CL2")? – user3514538

+0

@ user3514538 Pierwsza standardowa sekwencja konwersji jest rozważana przed drugą. To znaczy. jeśli istnieje "const", to jest dominujące. – Columbo

+1

@ user3514538 [over.match.copy] nie ma zastosowania, ponieważ zajmuje się inicjowaniem kopii (podczas gdy twój przykład pokazuje bezpośrednią inicjalizację). Również 'X' jest arbitralny, a więc obejmuje już jakiekolwiek kwalifikacje cv. – Columbo

Powiązane problemy