¿Cuál es la mejor manera de enlazar una referencia rvalue a un objeto dado o una copia temporal del mismo?estilo al vincular una referencia a objeto-o-dummy
A &&var_or_dummy = modify? static_cast<A&&>(my_A)
: static_cast<A&&>(static_cast<A>(my_A));
(Este código no funciona en mi reciente GCC 4.6 ... Recuerdo que funcione antes, pero ahora siempre devuelve una copia.)
En la primera línea, la static_cast
transforma my_A
de una lvalue a un xvalor. (C++ 0x §5.2.9/1-3) El static_cast
interno en la segunda línea realiza la conversión lvalue-a-rvalue, y el externo obtiene un valor x de este prvalue.
Esto parece ser compatible porque la referencia nombrada está vinculada condicionalmente al temporal según §12.2/5. El mismo truco funciona de la misma manera en C++ 03 con una referencia const
.
también puedo escribir la misma cosa menos verbosidad:
A &&var_or_dummy = modify? std::move(my_A)
: static_cast<A&&>(A(my_A));
Ahora es mucho más corto. La primera abreviatura es cuestionable: se supone que move
indica que algo le está sucediendo al objeto, no una mera combinación de valor lvalue-a-xvalor-a-valor. Confusamente, move
no se puede usar después del :
porque la llamada a la función interrumpiría el enlace temporal a referencia. La sintaxis A(my_A)
es quizás más clara que la static_cast
, pero es técnicamente equivalente a un modelo de estilo C.
también puedo ir hasta el final y escribir por completo en C-estilo arroja:
A &&var_or_dummy = modify? (A&&)(my_A) : (A&&)(A(my_A));
Después de todo, si esto va a ser un idioma, debe ser conveniente, y no es static_cast
realmente protegiéndome de cualquier cosa de todos modos: el peligro real es no vincular directamente al my_A
en el caso true
.
Por otro lado, esto fácilmente se ve dominado por el nombre de tipo repetido tres veces. Si A
fuera reemplazado por una plantilla grande y fea, realmente querría un atajo real.
(Tenga en cuenta que V
se evalúa sólo una vez a pesar de aparecer cinco veces :)
#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 como macros son, creo que es la mejor alternativa del montón. Es un poco peligroso porque devuelve un valor x, por lo que no debe usarse fuera de la inicialización de referencia.
Debe haber algo en lo que no haya pensado ... ¿sugerencias?
Sin macro, creo que puede cortar una mención más de tipo 'A' utilizando 'auto && var_or_dummy = ...'. No es que sea mucho mejor ... Para mi edificación: 'VAR_OR_DUMMY' no se puede implementar como una plantilla de función porque el temporal debe estar vinculado directamente a la referencia rvalue y devolver una referencia rvalue de una función no funcionará, a la derecha ? –
@James: ¿Puedo usar 'auto' de alguna manera en lugar de' remove_reference :: type'? ... Sí, eso es lo que pienso. Traté de hacer que devolviera una referencia lvalue también (ver el historial de edición) pero d'oh, no se permiten funciones. –
Potatoswatter
No, no creo que 'auto' se pueda usar en lugar de' remove_reference :: type' (aunque al buscarlo, descubrí que esto es válido: 'auto p = new auto (1);' ... 'p' tiene tipo' int * '). –