c++ and - Restituisce il tipo di '?:'(Operatore condizionale ternario)




order precedence (4)

Il tipo di ternario ?: Espressione è il tipo comune del suo secondo e terzo argomento. Se entrambi i tipi sono uguali, si ottiene un riferimento. Se sono convertibili l'uno con l'altro, uno viene scelto e l'altro viene convertito (promosso in questo caso). Poiché non è possibile restituire un riferimento lvalue a un valore temporaneo (la variabile convertita / promossa), il suo tipo è un tipo di valore.

Perché il primo restituisce un riferimento?

int x = 1;
int y = 2;
(x > y ? x : y) = 100;

Mentre il secondo no?

int x = 1;
long y = 2;
(x > y ? x : y) = 100;

In realtà, il secondo non è stato compilato affatto - "non è rimasto il valore di assegnazione".


Non può restituire un lvalue dal momento che dovrà implicitamente promuovere il tipo di x per abbinare il tipo di y (poiché entrambi i lati di : non sono dello stesso tipo), e con questo deve creare un valore temporaneo.

Cosa dice lo standard? ( n1905 )

Espressioni 5.17 Operatori di assegnazione e assegnazione di composti

5.17 / 3

Se il secondo e il terzo operando hanno tipi diversi e hanno un tipo di classe (possibilmente qualificato cv), viene fatto un tentativo per convertire ciascuno di questi operandi al tipo dell'altro. Il processo per determinare se un'espressione di operando E1 di tipo T1 può essere convertita per corrispondere a un'espressione di operando E2 di tipo T2 è definita come segue:

- Se E2 è un lvalue: E1 può essere convertito per corrispondere a E2 se E1 può essere convertito implicitamente (clausola 4) al tipo "riferimento a T2", soggetto al vincolo che nella conversione il riferimento deve legare direttamente (8.5.3 ) a E1.

- Se E2 è un valore rvalore o se la conversione sopra non può essere eseguita:

- se E1 ed E2 hanno un tipo di classe e i tipi di classe sottostanti sono uguali o uno è una classe base dell'altro: E1 può essere convertito per corrispondere a E2 se la classe di T2 è dello stesso tipo di, o una classe base di , la classe di T1 e la qualifica di cv di T2 è la stessa qualifica di cv o una qualifica di cv maggiore rispetto alla qualifica di cv di T1. Se la conversione viene applicata, E1 viene modificato in un valore rvalore di tipo T2 che fa ancora riferimento all'oggetto di classe di origine originale (o al rispettivo subobject corrispondente). [ Nota: cioè, non viene effettuata alcuna copia. - end note ] mediante copia-inizializzazione di un temporaneo di tipo T2 da E1 e utilizzo di tale temporaneo come operando convertito.

Altrimenti (cioè, se E1 o E2 ha un tipo non di classe, o se entrambi hanno tipi di classe ma le classi sottostanti non sono uguali o una classe base dell'altro): E1 può essere convertito per corrispondere a E2 se E1 può essere implicitamente convertito nel tipo che l'espressione E2 avrebbe se E2 fosse convertito in un valore di rvalue (o il tipo che ha, se E2 è un valore di rvalore).

Utilizzando questo processo, viene determinato se il secondo operando può essere convertito in modo che corrisponda al terzo operando e se il terzo operando possa essere convertito in modo che corrisponda al secondo operando. Se entrambi possono essere convertiti, o uno può essere convertito ma la conversione è ambigua, il programma è mal formato. Se nessuno dei due può essere convertito, gli operandi rimangono invariati e viene effettuato un ulteriore controllo come descritto di seguito. Se è possibile eseguire esattamente una conversione, tale conversione viene applicata all'operando scelto e l'operando convertito viene utilizzato al posto dell'operando originale per il resto di questa sezione.

5.17 / 4

Se il secondo e il terzo operando sono lvalue e hanno lo stesso tipo, il risultato è di quel tipo ed è un lvalue ed è un campo-bit se il secondo o il terzo operando è un campo-bit, o se entrambi sono bit- campi.

5.17 / 5

Altrimenti, il risultato è un valore. Se il secondo e il terzo operando non hanno lo stesso tipo e hanno un tipo di classe (eventualmente qualificata per il cv), viene utilizzata la risoluzione di sovraccarico per determinare le conversioni (se presenti) da applicare agli operandi (13.3.1.2, 13.6) . Se la risoluzione di sovraccarico fallisce, il programma è mal formato. Altrimenti, vengono applicate le conversioni così determinate e gli operandi convertiti vengono utilizzati al posto degli operandi originali per il resto di questa sezione.


Le espressioni non hanno tipi di ritorno, hanno un tipo e - come è noto nell'ultimo standard C ++ - una categoria di valore.

Un'espressione condizionale può essere un lvalue o un valore . Questa è la sua categoria di valore. (Questo è in qualche modo una semplificazione, in C++11 abbiamo lvalues, xvalues ​​e prvalues.)

In termini molto ampi e semplici, un lvalue si riferisce a un oggetto in memoria e un valore di rvalore è solo un valore che potrebbe non essere necessariamente associato a un oggetto in memoria.

Un'espressione di assegnazione assegna un valore a un oggetto in modo che la cosa a cui è assegnato debba essere un lvalue .

Affinché un'espressione condizionale ( ?: :) Sia un lvalue (di nuovo, in termini generici e semplici), il secondo e il terzo operando devono essere lvalue dello stesso tipo . Questo perché la categoria di tipo e valore di un'espressione condizionale viene determinata al momento della compilazione e deve essere appropriata indipendentemente dal fatto che la condizione sia vera o meno. Se uno degli operandi deve essere convertito in un tipo diverso per corrispondere all'altro, l'espressione condizionale non può essere un lvalue in quanto il risultato di questa conversione non sarebbe un lvalue .

Riferimenti ISO / IEC 14882: 2011:

3.10 [basic.lval] Lvalues ​​e rvalues ​​(sulle categorie di valori)

5.15 [expr.cond] Operatore condizionale (regole per quale tipo e categoria di valori ha un'espressione condizionale)

5.17 [expr.ass] Operatori di assegnazione e di assegnazione composta (requisito che gli lhs di un incarico debbano essere un lvalue modificabile)


Il valore di ritorno di main()mostra come il programma è uscito. Se il valore di ritorno è zerosignifica che l'esecuzione è avvenuta con successo mentre qualsiasi valore diverso da zero rappresenterà che qualcosa è andato male nell'esecuzione.





c++ types reference conditional-operator lvalue