Quelle est la meilleure façon de lier une référence rvalue à un objet donné ou une copie temporaire de celui-ci?style dans la liaison d'une référence à l'objet-ou-dummy
A &&var_or_dummy = modify? static_cast<A&&>(my_A)
: static_cast<A&&>(static_cast<A>(my_A));
(Ce code ne fonctionne pas sur mon récent GCC 4.6 ... Je me souviens qu'il travaille avant, mais maintenant il renvoie toujours une copie.)
Sur la première ligne, la static_cast
transforme my_A
d'un lvalue à une valeur x. (C++ 0x §5.2.9/1-3) Le static_cast
intérieur sur la deuxième ligne effectue la conversion lvalue-à-valeur, et l'externe obtient une valeur x à partir de cette prvalue.
Cela semble être pris en charge car la référence nommée est conditionnellement liée au temporaire par §12.2/5. La même astuce fonctionne de la même manière en C++ 03 avec une référence const
.
Je peux aussi écrire la même chose moins verbeux:
A &&var_or_dummy = modify? std::move(my_A)
: static_cast<A&&>(A(my_A));
Maintenant, il est beaucoup plus courte. La première abréviation est discutable: move
est censé signaler que quelque chose se passe à l'objet, pas un simple mélange lvalue-à-xvalue-à-lvalue. Confusément, move
ne peut pas être utilisé après le :
car l'appel de la fonction interrompt la liaison temporaire à référence. La syntaxe A(my_A)
est peut-être plus claire que la static_cast
, mais elle est techniquement équivalente à une distribution de type C.
Je peux aussi aller tout le chemin et l'écrire entièrement en style C moulages:
A &&var_or_dummy = modify? (A&&)(my_A) : (A&&)(A(my_A));
Après tout, si cela va être un idiome, il doit être pratique et static_cast
n'est pas vraiment me protéger de toute façon - le vrai danger est de ne pas lier directement à my_A
dans le cas true
. D'autre part, cela est facilement dominé par le nom de type répété trois fois. Si A
ont été remplacés par un gros ID de modèle moche, je voudrais vraiment un vrai raccourci.
(Notez que V
est évalué qu'une seule fois malgré apparaissant cinq fois :)
#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)))
hackish comme les macros sont, je pense que c'est la meilleure alternative du groupe. C'est un peu dangereux car il renvoie une valeur x, il ne devrait donc pas être utilisé en dehors de l'initialisation de la référence.
Il doit y avoir quelque chose que je n'ai pas pensé ... des suggestions?
Sans macro, je pense que vous pouvez supprimer une des mentions de type 'A' en utilisant' auto && var_or_dummy = ... '. Pas que ce soit beaucoup mieux ... Pour mon édification: 'VAR_OR_DUMMY' ne peut pas être implémenté en tant que modèle de fonction car le temporaire doit être lié directement à la référence rvalue et renvoyer une référence rvalue à partir d'une fonction ne fonctionnera pas, ? –
@James: Puis-je utiliser 'auto' d'une façon ou d'une autre à la place de' remove_reference :: type'? ... Oui, c'est ma pensée. J'ai essayé de lui faire renvoyer une référence lvalue aussi (voir l'historique des modifications) mais d'oh, aucune fonction n'est permise. –
Potatoswatter
Non, je ne pense pas que 'auto' peut être utilisé à la place de' remove_reference :: type' (bien qu'en regardant ça, j'ai découvert que c'est valide: 'auto p = new auto (1);' ... 'p' a le type' int * '). –