Qual è il modo migliore per associare un riferimento di rvalue a un determinato oggetto o una copia temporanea di esso?nel collegamento di un riferimento a object-or-dummy
A &&var_or_dummy = modify? static_cast<A&&>(my_A)
: static_cast<A&&>(static_cast<A>(my_A));
(Questo codice non funziona sul mio recente GCC 4.6 ... Ricordo che funziona prima, ma ora si ritorna sempre una copia.)
Nella prima riga, il static_cast
trasforma my_A
da un lvalue su un valore x. (C++ 0x §5.2.9/1-3) Il numero interno static_cast
sulla seconda riga esegue la conversione da lvalue a rvalue e quello esterno ottiene un valore x da questo valore.
Questo sembra essere supportato perché il riferimento nominato è condizionalmente vincolato al temporaneo per §12.2/5. Lo stesso trucco funziona allo stesso modo in C++ 03 con un riferimento const
.
posso anche scrivere la stessa cosa meno verboso:
A &&var_or_dummy = modify? std::move(my_A)
: static_cast<A&&>(A(my_A));
Ora è molto più breve. La prima abbreviazione è discutibile: si suppone che il segnale move
segnali che qualcosa sta accadendo all'oggetto, non un semplice shuffle da lvalue a xvalue-to-lvalue. In modo confuso, move
non può essere utilizzato dopo lo :
perché la chiamata di funzione interromperebbe l'associazione temporanea al riferimento. La sintassi A(my_A)
è forse più chiara dello static_cast
, ma è tecnicamente equivalente a un cast in stile C.
posso anche andare fino in fondo e scrivere interamente in C-style calchi:
A &&var_or_dummy = modify? (A&&)(my_A) : (A&&)(A(my_A));
Dopo tutto, se questo sta per essere un linguaggio, deve essere conveniente, e non è static_cast
mi sta davvero proteggendo da qualsiasi cosa - il vero pericolo non è riuscire a legare direttamente a my_A
nel caso true
.
D'altra parte, questo è facilmente dominato dal nome tipografico ripetuto tre volte. Se lo A
venisse sostituito con un modello di identificazione grande e brutto, vorrei davvero una vera scorciatoia.
(Si noti che V
viene valutata solo una volta pur apparendo cinque volte :)
#define VAR_OR_DUMMY(C, V) ((C)? \
static_cast< typename std::remove_reference< decltype(V) >::type && >(V) \
: static_cast< typename std::remove_reference< decltype(V) >::type && > ( \
static_cast< typename std::remove_reference< decltype(V) >::type >(V)))
hacker come macro sono, penso che sia la migliore alternativa del gruppo. È un po 'pericoloso perché restituisce un valore x, quindi non dovrebbe essere usato al di fuori dell'inizializzazione del riferimento.
Deve esserci qualcosa a cui non ho pensato ... suggerimenti?
Senza una macro penso che si possa ritagliare un'altra delle menzioni di tipo 'A' usando' auto && var_or_dummy = ... '. Non che sia molto meglio ... Per la mia edificazione: 'VAR_OR_DUMMY' non può essere implementato come un modello di funzione perché il temporaneo deve essere associato direttamente al riferimento di rvalue e il ritorno di un riferimento di rvalue da una funzione non funzionerà, a destra ? –
@James: Posso usare 'auto' in qualche modo invece di' remove_reference :: type'? ... Sì, questo è il mio pensiero. Ho provato a fare in modo che restituisca un riferimento lvalue (vedi la cronologia delle modifiche) ma d'oh, nessuna funzione è permessa. –
Potatoswatter
No, non penso che 'auto' possa essere usato al posto di' remove_reference :: type' (sebbene, osservandolo, ho scoperto che questo è valido: 'auto p = new auto (1);' ... 'p' ha tipo' int * '). –