2016-06-22 2 views
6

J'ai donc demandé this question et j'ai été bricoler avec la résolution via static_cast. (Soit dit en passant, il ne résout le problème, je ne suis pas sûr si je comprends pourquoi.)Qu'est-ce que static_cast <T> fait à un T &?

Dans le code:

vector<int> foo = {0, 42, 0, 42, 0, 42}; 
replace(begin(foo), end(foo), static_cast<int>(foo.front()), 13); 

Est-ce le static_cast construire simplement un R-Value int? Quelle est la différence entre cela et simplement l'appel:

replace(begin(foo), end(foo), int{foo.front()}, 13); 

EDIT:

En déduire les réponses static_cast-t semblent construire un R-Value int: http://ideone.com/dVPIhD

Mais cette le code et non fonctionne sur Visual Studio 2015. S'agit-il d'un bogue de compilateur? Testez ici: http://webcompiler.cloudapp.net/

+0

Je n'ai pas la citation de toute norme pour me soutenir, mais je pense que vous pouvez utiliser '+ foo.front()' pour obtenir une copie de la valeur, au lieu d'une référence au symbole – KABoissonneault

Répondre

6
  1. Oui, il est le même que int{...}, à moins que .front() retourné un type qui a nécessité une conversion de rétrécissement. Dans ce cas, int(...) serait identique. En cas d'erreur du programmeur, la distribution statique est légèrement moins susceptible de faire quelque chose de dangereux, comme de convertir un pointeur en un int que int(...).

Remarque éliminant les résultats de la coulée dans un comportement non défini comme l'élément avant est modifié par l'opération de remplacement, ce qui pourrait briser std::replace.

J'utiliser

template<class T> 
std::decay_t<T> copy_of(T&& t){return std::forward<T>(t); } 

moi-même ici.

Quant à savoir pourquoi cela ne fonctionne pas dans MSVC ...

MSVC prend obligeamment des situations où vous CAST une variable de type T à un T et procède à ne rien faire. Cela casse votre code.

Il existe un compiler flag (/Zc:rvalueCast) que vous pouvez utiliser pour que MSVC ne casse plus votre code.

+0

Est-ce que 'copy_of'standard, ou vous dites que je devrais juste l'implémenter? –

+0

@jona Je suggérais de mettre en œuvre cela, car il a un certain nombre de cas d'utilisation, et élimine la répétition de type inutile. – Yakk

+0

J'ai donc clarifié ma question en soulignant la différence entre Visual Studio et gcc. Désolé de déplacer les poteaux de but sur vous. –

5

La fonction membre front renvoie une référence au premier élément d'un vecteur non vide.

D'un autre côté algorithme standard replace déclaré comme

template <class ForwardIterator, class T> 
    void replace (ForwardIterator first, ForwardIterator last, 
       const T& old_value, const T& new_value) 

prend le troisième paramètre également par référence. Ainsi, en général, le premier élément du vecteur peut être modifié par l'algorithme et le résultat du traitement d'autres éléments du vecteur par l'algorithme peut être incorrect.En utilisant static_cast, un objet temporaire est créé et ne sera pas modifié par l'algorithme. Ainsi, le traitement de tous les éléments du vecteur sera correct.

En ce qui me concerne, j'ai suggéré une proposition C++ pour utiliser le mot-clé auto dans de tels cas. Par exemple

replace(begin(foo), end(foo), auto(foo.front()), 13); 
+1

La suggestion 'auto' est très élégante. +1 –

+1

La suggestion automatique ne parvient pas à compiler: http://coliru.stacked-crooked.com/a/27328ba4ae68d68d – NathanOliver

+1

@NathanOliver Comme dit dans la réponse, c'est juste une proposition – KABoissonneault