2014-10-22 10 views
15

LetIl risultato di un cast è un valore?

Poi è (int)a un rvalue nello standard C++?

compilatori diversi mostrano risultati diversi per questo codice:

#include <iostream> 
using namespace std; 

void f(int& x) 
{ 
    cout << "l value" << endl; 
} 

void f(int&& x) 
{ 
    cout << "r value" << endl; 
} 

int main() 
{ 
    int a = 0; 
    f((int)a); 
} 

compilatori con risultati diversi:

1) http://cpp.sh/2r6

2) http://webcompiler.cloudapp.net/

+0

Qualcuno ha controllato per vedere se c'è ancora un bug [connect] (http://connect.microsoft.com)? Una ricerca rapida non ne ha risolti uno. – Mgetz

+0

@Mgetz Stavo cercando, non ho trovato nulla di ovvio però. –

+0

[Archiviato come difetto alla connessione] (https://connect.microsoft.com/VisualStudio/feedback/details/1008261) contro VS2013 utilizzando il test case di @ ShafikYaghmour – Mgetz

risposta

10

Il dovrebbe essere un rvalue ma Webcompiler esegue Visual Studio e Visual Studio ha un extension which allows temporary objects to be bound to non-const lvalue references.a bug/extension that casues it to generate an lvalue in this case Come indicato sopra, Igor può essere disabilitato utilizzando /Za (see it live).

Possiamo vedere che dovrebbe essere un rvalue (specificamente un prvalue) dal progetto C++ sezione standard 5.4tipo di conversione esplicita (notazione cast) paragrafo che dice (sottolineatura mia) :

il risultato dell'espressione (T) Cast-espressione è di tipo T. il risultato è un lvalue se T è un tipo di riferimento lvalue o un rvalue riferimento al tipo di funzione e un valore x se T è un riferimento di valore al tipo di oggetto; altrimenti il ​​risultato è un valore nominale. [Nota: se T è un tipo non di classe qualificato cv, i qualificatori cv vengono ignorati quando si determina il tipo del valore risultante; vedi 3.10. -end nota]

Sia gcc e clang risultato nella rvalue che è il risultato atteso.

Per inciso, consiglierei di utilizzare rextester su webcompiler poiché rextester consente di condividere il programma e ha anche condivisione dal vivo.

Aggiornamento

Ben Voigt sottolineare questo bug report e così sembra che Visual Studio in realtà produce un lvalue . Quindi questo non è semplicemente un caso di extension which allows temporary objects to be bound to non-const lvalue references.

Come dyp indica anche gcc used to have a cast to lvalue extension.

Update 2

Mgetz ha presentato una bug report, la risposta è stata che questo viene fissato usando il /Zc:rvalueCast flag, la descrizione della bandiera è la seguente:

Quando l'/ Zc: rvalueCast l'opzione è specificata, il compilatore correttamente identifica un tipo di riferimento di rvalore come risultato di un'operazione di cast in conformità con lo standard C++ 11. Se l'opzione non è specificata , il comportamento del compilatore è lo stesso di Visual Studio 2012. Per impostazione predefinita,/Zc: rvalueCast è disattivato. Per la conformità e per eliminare gli errori nell'uso dei cast, si consiglia di utilizzare/Zc: rvalueCast.

Non è chiaro se questo flag sarà abilitato per impostazione predefinita nelle versioni future.

+0

+1 per la tua raccomandazione. quanto dura il collegamento per la condivisione live? – user2029077

+0

@MinimusHeximus non sono sicuro, ho usato solo per brevi periodi e il sito non lo documenta. –

+0

Questa risposta è sbagliata, in realtà. Visual C++ non sta usando la disfunzione che lega un riferimento lvalue ad un temporaneo .... non riesce affatto a creare un temporaneo. Vedi la risposta di Matt e la mia segnalazione di bug https://connect.microsoft.com/VisualStudio/Feedback/Details/615622 –

4

Sì, il risultato di un cast a un tipo di oggetto è un valore , come specificato da C++ 11 5.4/1:

Il risultato è un lvalue se T è un Ivalue riferimento tipo o un riferimento rvalue operato del tipo e un xValue se T è un riferimento all'oggetto rvalue tipo; in caso contrario il risultato è un valore prenativo.

+6

La chiave è che non esiste alcuna regola che faccia un'eccezione per un cast da 'T' a' T'. –

3

In Standard C++ int(a) e (int)a sono rvalue (le altre risposte forniscono riferimenti standard).

L'esempio di codice sta sfruttando un bug/estensione in MSVC, ma non come sembra a prima vista. Come si può vedere da questo codice che funziona in MSVC:

#include <iostream> 

int main() 
{ 
    int x = 0; 
    (int)x = 1; 
    std::cout << x << std::endl; 
} 

MSVC tratta (int)x come valore assegnabile.

Anche se MSVC ha un'estensione che consente ai rvalues ​​di collegarsi a riferimenti non const; quell'estensione continua a far corrispondere meglio i riferimenti rvalue rispetto ai riferimenti lvalue per rvalue.

+1

Ho segnalato questo e molte altre varianti su Connect quattro anni fa: https://connect.microsoft.com/VisualStudio/Feedback/Details/615622 –

Problemi correlati