2017-04-02 3 views
6

Je lisais la documentation std::for_each ici http://en.cppreference.com/w/cpp/algorithm/for_each et vu que la valeur de retour est std::move(f)Pourquoi est-ce for_each retour fonction en mouvement

Pourquoi la norme déplacer le paramètre appliquer d'entrée de la valeur de retour? Ne sera-t-il pas déplacé par défaut, puisque le paramètre d'entrée est passé par valeur?


Cela me conduit à quelques followups, lorsque vous compilez le code suivant

Something function(Something something) { 
    return something; 
} 
  1. La déclaration de retour est un mouvement sur mon système avec le niveau d'optimisation le plus élevé (-O3), pourquoi la plupart des compilateurs n'élisent-ils pas cette valeur de retour? Les valeurs locales sont élidées mais les arguments de fonction ne le sont pas.

  2. Est-ce que C++ 17 impose l'élision dans ce cas? J'ai lu la proposition (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html) mais je ne comprends pas complètement quels cas sont admissibles à l'élision obligatoire.

J'ai essayé sur Apple LLVM version 8.0.0 (clang-800.0.42.1) sur mon Mac et g++ 5.4 sur Ubuntu 16.04.

Répondre

11

Ceci est dû à une modification de dernière minute des règles de sémantique de mouvement pour C++ 11. The original move proposal ne s'est pas déplacé automatiquement lorsque les arguments de la fonction par valeur apparaissaient dans la clause de retour. Cependant, à la fin du processus C++ 11, cette fonctionnalité de langue a été ajoutée.

Avant l'ajout de la fonction de langue, for_each "a été déplacé". À ce moment, le déménagement sur la déclaration de retour était nécessaire. Mais il est devenu inutile, mais inoffensif au moment où C++ 11 livré.

LWG issue 2747 corrigé cela pour C++ 17. En ce qui concerne votre première question de suivi, je ne suis pas un rédacteur de compilateur, mais ma meilleure estimation est la suivante: Il n'est actuellement pas légal d'éluder le retour d'un paramètre de fonction (que je connais), et je suppose que pourquoi ce n'est pas légal, c'est que personne n'a compris comment le mettre en œuvre, et donc personne n'a eu la motivation de changer la norme pour la rendre légale.

Deuxième suivi: Non, C++ 17 n'applique pas l'élision dans ce cas. Les règles restent les mêmes que pour C++ 11 dans ce cas, sauf pour le fait que le déplacement redondant de for_each n'est plus spécifié.

D'après les commentaires ci-dessous:

Pourquoi dites-vous que ce n'est pas légal de elide le retour d'un paramètre de fonction?

Je fais référence N4660, qui est C++ 17, mais il est libellé similaire dans C de 98/03/11/14 ... sauvegarde, il a récemment été protégé. Voir N4659 à la place (tout aussi bon):

15.8.3 Copier/déplacer l'élision [class.copy.élision]

  1. Lorsque certains critères sont respectés, une mise en œuvre est permis d'omettre la construction copier/déplacer d'un objet de classe, ...

    • dans un communiqué return dans une fonction avec un type de retour de classe, lorsque l'expression est le nom d'un objet automatique non volatile (autre qu'un paramètre de fonction ou une variable introduit par le exception déclaration d'un handl er (18,3)) avec le même type (en ignorant cv-qualification) comme type de retour de la fonction, l'opération de copie/déplacement peut être omise en construisant l'objet automatique directement dans l'objet de retour de l'appel de fonction

Ce langage spécifiquement élision de n'autorise les paramètres de fonction.

+0

Pourquoi dites-vous que ce n'est pas légal de elide le retour d'un paramètre de fonction? La façon dont je vois les valeurs des paramètres de la fonction sont les mêmes que les variables locales sauf que l'ordre de construction et de destruction n'est pas spécifié. – Curious

+0

@Curious: Mise à jour avec une citation de C++ 17 pour résoudre ce problème. –

+0

Une dernière chose. Pourquoi la proposition a-t-elle refusé l'élision des arguments de fonction? J'essaie juste de comprendre le raisonnement derrière la décision. – Curious