Restituisce il tipo di "?:" (Operatore condizionale ternario)


208

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 dell'incarico".


1
hmm, è come trovare un caso speciale per cuocere il pane, non è arrivato a questo una volta
Ulterior


Poiché l'assegnazione di un tipo all'espressione implicherebbe un cast di almeno un termine, questo termine non sarebbe più un valore l.
Yves Daoust,

Risposte:


173

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

Un'espressione condizionale può essere un lvalue o un rvalue . Questa è la sua categoria di valore. (Questa è in qualche modo una semplificazione, inC++11 cui abbiamo valori, valori x e valori.)

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

Un'espressione di assegnazione assegna un valore a un oggetto, quindi l'elemento a cui deve essere assegnato deve essere un valore .

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

Riferimenti ISO / IEC 14882: 2011:

3.10 [basic.lval] Valori e valori (sulle categorie di valori)

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

5.17 [expr.ass] Operatori di assegnazione e assegnazione composti (requisito che il valore minimo di un'assegnazione deve essere un valore modificabile)


3
E quando ho letto su xvalue e prvalue (dal momento che non avevo sentito parlare di loro prima della tua risposta) mi sono imbattuto in questo pratico post SO: stackoverflow.com/questions/3601602/…
soffice

an rvalue is just a value that may not necessarily be *attached* to an object in memory.Puoi spiegarlo in un modo più semplice? . Inoltre cosa intendi con type and value *category*? Grazie
Mr. Anubis

@SoulReaper: prvalue, xvalue, glvaluesono categorie di valore.
Xeo,

@Xeo Apprezzo l'aiuto, ma puoi dire che cosa intende per valore è solo un valore che potrebbe non essere necessariamente collegato a un oggetto in memoria. ? con esempio?
Mr. Anubis,

@SoulReaper: Penso che stia parlando di cose come true, this, enumvalori. Quelle cose sono valori (valori "puri"), ma non vivono nella memoria.
Xeo,

57

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


ma y maggiore di x, quindi non è necessario in promozione per questo caso particolare, può restituire riferimento a y. Hmm ... Ma sono d'accordo, sarebbe strano.
Yola,

1
@ Mr.TAMER: preferirei scavare attraverso lo standard. : <
Xeo,

3
@Yola: poiché i tipi sono un concetto di tempo di compilazione in C ++, il valore restituito effettivo dell'espressione non ha importanza.
Xeo,

1
Non si ottiene un riferimento indietro, si ottiene lvalue.
Suma,

1
@Xeo: non nella terminologia C ++, però;)
Sebastian Mach,

19

Non può restituire un valore poiché dovrà promuovere implicitamente il tipo di xin modo che corrisponda al tipo di y(poiché entrambi i lati :non sono dello stesso tipo) e con ciò deve creare un temporaneo.


Cosa dice lo standard? ( n1905 )

Espressioni 5.17 Operatori di assegnazione e assegnazione composti

5.17 / 3

Se il secondo e il terzo operando hanno tipi diversi e uno dei due ha un tipo di classe (possibilmente qualificato in cv), si tenta di convertire ciascuno di questi operandi nel 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 è definito come segue:

- Se E2 è un lvalue: E1 può essere convertito in corrispondenza di E2 se E1 può essere implicitamente convertito (clausola 4) nel tipo "riferimento a T2", fatto salvo il vincolo che nella conversione il riferimento deve legare direttamente (8.5.3 ) a E1.

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

- se E1 ed E2 hanno un tipo di classe e i tipi di classe sottostanti sono uguali o uno è una classe di base dell'altro: E1 può essere convertito in corrispondenza di E2 se la classe di T2 è dello stesso tipo o una classe di 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 viene applicata la conversione, E1 viene modificato in un valore di tipo T2 che fa ancora riferimento all'oggetto della classe di origine originale (o al relativo oggetto secondario appropriato). [ Nota: ovvero, non viene effettuata alcuna copia. - nota finale ] copiando l'inizializzazione di un temporaneo di tipo T2 da E1 e usando quel 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 né uguali né una una classe base dell'altra): E1 può essere convertito in corrispondenza di E2 se E1 può essere implicitamente convertito nel tipo che avrebbe l'espressione E2 se E2 fosse convertito in un valore (o nel tipo che ha, se E2 è un valore).

Utilizzando questo processo, viene determinato se il secondo operando può essere convertito in modo da corrispondere al terzo operando e se il terzo operando può essere convertito in modo da corrispondere 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 vengono eseguiti ulteriori controlli come descritto di seguito. Se è possibile esattamente una conversione, quella conversione viene applicata all'operando scelto e l'operando convertito viene usato al posto dell'operando originale per il resto di questa sezione.


5.17 / 4

Se il secondo e il terzo operando sono valori e hanno lo stesso tipo, il risultato è di quel tipo ed è un valore e è un campo di bit se il secondo o il terzo operando è un campo di 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 ed entrambi hanno un tipo di classe (possibilmente qualificato in cv), la risoluzione di sovraccarico viene utilizzata per determinare le conversioni (se presenti) da applicare agli operandi (13.3.1.2, 13.6) . Se la risoluzione del 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.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.