2015-08-27 33 views
9

Czy istnieją reguły dotyczące niejawnej konwersji typów dla argumentów operatora trójskładnikowego?C++: Ternary Operator (operator warunkowy) i jego zasady konwersji niejawnych typów

Operator trójki musi zawsze zwracać ten sam typ. Ten typ jest określany wyłącznie przez drugi i trzeci argument (1st ? 2nd : 3rd), dlatego oba argumenty są konwertowane na ten typ. W jaki sposób określa się ten typ?

A dokładniej, to badane przykład:

class pointclass 
{ 
    pointclass(); 

    pointclass(int i); // (pointclass)(int) 
    operator bool() const; // (bool)(pointclass) 
}; 

mam klasy (pointclass), która umożliwia konwersję niejawny z int do pointclass i ukryta konwersji z pointclass do bool.

int i; 
pointclass p; 
bool b; 

b ? p : i; // (bool) ? (int)(bool)(pointclass) : (int) 
b ? i : p; // (bool) ? (int) : (int)(bool)(pointclass) 

pomocą operatora potrójny, porównuję pointclass i int. Kompilator używa niejawnej konwersji z pointclass do bool, a następnie standardowej konwersji z bool na int. Odbywa się to bez względu na to, czy wymieniam 2. i 3. argumenty. Dlaczego to nie konwertuje int na pointclass?

Stosując operator porównania jest znacznie bardziej prosta:

p == i;  // (pointclass) == (pointclass)(int) 
i == p;  // (int) == (int)(bool)(pointclass) 

rodzaju argumentów jest po prostu określona przez pierwszy argument.

Ale nie rozumiem reguł konwersji typu operatora trójskładnikowego. Wydaje mi się, że używasz sposobu większości konwersji.

+0

Tak, reguły są w [expr.cond] w standardzie. – chris

+0

Ktoś bardziej zorientowany w sposób standardowy niż ja może udzielić autorytatywnej odpowiedzi, ale z reguły zamieniają się one na "najbliższy" wspólny typ, na który mogą być konwertowane. – SergeyA

+0

Jeśli myślisz, że C++ robi fajne rzeczy, oszczędzaj myśli dla biednych gości z Java. – Bathsheba

Odpowiedz

6

Cytowanie MSDN:

wyrażenia warunkowe mają prawo-lewo skojarzenie. Pierwszy operand musi być typu integralnego lub wskaźnikowego. Następujące reguły obowiązują od do drugiego i trzeciego argumentu:

Jeśli oba operandy są tego samego typu, wynik jest tego samego typu.

Jeśli oba operandy są typu arytmetycznego lub wyliczeniowego, zwykle wykonywane są konwersje arytmetyczne (objęte konwersjami arytmetycznymi): wykonywane w celu przekonwertowania ich na typ wspólny.

Jeśli oba operandy są typu wskaźnikowego lub jeden jest typem wskaźnika, a drugi jest wyrażeniem stałym, które zwraca wartość 0, wykonywane są konwersje, aby przekonwertować je na typ wspólny.

Jeśli oba operandy są typu referencyjnego, wykonywane są konwersje referencyjne w celu przekonwertowania ich na typ wspólny.

Jeśli oba operandy są typu void, typem wspólnym jest void.

Jeśli oba operandy są tego samego typu zdefiniowanego przez użytkownika, typem wspólnym jest ten typ.

Jeśli operandy mają różne typy i co najmniej jeden z operandów ma typ zdefiniowany przez użytkownika, wówczas reguły językowe są używane do określenia wspólnego typu dla . (Patrz ostrzeżenie poniżej.)

Zasadniczo to, że kompilator C++ szuka wspólnego typu dla drugiego i trzeciego operandu. Jeśli może go znaleźć, to jest typ wyniku. Jeśli nie może go znaleźć, powoduje to błąd czasu kompilacji.

Jeśli chcesz zobaczyć standardową pozycję, możesz zobaczyć zasady in working draft for newest standard, 5.16 (strona 129).

dzień nie konwersja int do pointclass - zasadą ogólną jest, że zawsze iść w dół hierarchii, a nie w górę - wyobrazić bardziej zaawansowanej klasy hierarchii; gdzieś tam może być dziesiątki sposobów na konwersję obu typów do innej klasy, ale czy to naprawdę jest to, czego chcesz? Co więcej, określenie, której klasy użyć, może być niemożliwe. Dlatego spuszczamy.

+0

Dziękuję za tę odpowiedź. Rozumiem, Warunkowy operator zawsze konwertuje w dół hierarchii, gdzie standardowy typ jest niższy niż klasa. Problem wynikał z niejawnych konwersji między standardowymi typami. Mogłabym zapobiec tym konwersjom, definiując (domyślnie) operatorów konwersji pomiędzy 'pointclass' a wszystkimi standardowymi typami z wyjątkiem' bool' jako 'protected'. Dzięki! – dib