Frage C ++: Ternärer Operator (Bedingter Operator) und seine Implicit Type Conversion Rules


Gibt es Regeln für die implizite Typkonvertierung für Argumente des ternären Operators?

Der ternäre Operator muss immer den gleichen Typ zurückgeben. Dieser Typ wird ausschließlich durch das zweite und dritte Argument bestimmt (1st ? 2nd : 3rd), daher werden beide Argumente in diesen Typ konvertiert. Wie wird dieser Typ bestimmt?

Um genauer zu sein, habe ich ein Beispiel getestet:

class pointclass
{
    pointclass();

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

Ich habe ein klasse (pointclass), die implizite Konvertierung von ermöglicht int zu pointclass und implizite Konvertierung von pointclass zu bool.

int i;
pointclass p;
bool b;

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

Mit dem ternären Operator vergleiche ich pointclass und int. Der Compiler verwendet implizite Konvertierung von pointclass zu bool und dann die Standardkonvertierung von bool zu int. Dies geschieht, egal ob ich das zweite und dritte Argument tausche. Warum konvertiert es nicht? int zu pointclass?

Die Verwendung eines Vergleichsoperators ist viel einfacher:

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

Der Typ der Argumente wird einfach durch das erste Argument bestimmt.

Aber ich verstehe die Typumwandlungsregeln des ternären Operators nicht. Für mich scheint es, als würde man den Weg der meisten Conversions nutzen.


9
2017-08-27 13:59


Ursprung


Antworten:


Zitieren MSDN:

Bedingte Ausdrücke haben eine Assoziation von rechts nach links. Der Erste   Der Operand muss vom Integral- oder Zeigertyp sein. Die folgenden Regeln gelten   zu den zweiten und dritten Operanden:

Wenn beide Operanden vom selben Typ sind, ist das Ergebnis von diesem Typ.

Wenn beide Operanden arithmetische oder Aufzählungstypen sind, sind die üblichen arithmetischen Konvertierungen (in Arithmetic Conversions abgedeckt)   durchgeführt, um sie in einen gemeinsamen Typ zu konvertieren.

Wenn beide Operanden von Zeigertypen sind oder wenn der eine ein Zeigertyp und der andere ein konstanter Ausdruck ist, der zu 0 ausgewertet wird, Zeiger   Konvertierungen werden durchgeführt, um sie in einen gemeinsamen Typ zu konvertieren.

Wenn beide Operanden Referenztypen sind, werden Referenzkonvertierungen durchgeführt, um sie in einen gemeinsamen Typ zu konvertieren.

Wenn beide Operanden vom Typ void sind, ist der allgemeine Typ void.

Wenn beide Operanden vom selben benutzerdefinierten Typ sind, ist der allgemeine Typ dieser Typ.

Wenn die Operanden unterschiedliche Typen haben und mindestens einer der Operanden einen benutzerdefinierten Typ hat, werden die Sprachregeln verwendet   Bestimmen Sie den allgemeinen Typ. (Siehe Warnung unten.)

Im Wesentlichen sucht der C ++ - Compiler nach dem gemeinsamen Typ für den zweiten und dritten Operanden. Wenn es es finden kann, ist das der Ergebnistyp. Wenn es nicht gefunden werden kann, führt dies zu einem Fehler bei der Kompilierung.

Wenn Sie die Standardposition sehen möchten, können Sie die Regeln sehen im Arbeitsentwurf für den neusten Standart, 5.16 (Seite 129).

Da nicht int in Punktklasse umgewandelt wird - allgemeine Regel ist, dass Sie Geh immer in die Hierarchie, nicht nach oben - Stellen Sie sich eine erweiterte Klassenhierarchie vor; Irgendwo oben könnte es Dutzende Möglichkeiten geben, beide Typen in eine andere Klasse zu konvertieren, aber ist das wirklich was du willst? Darüber hinaus könnte die Bestimmung der zu verwendenden Klasse unmöglich sein. Deshalb sind wir niedergeschlagen.


6
2017-08-27 14:05