J'ai lu récemment que [[nodiscard]]
en C++17, et d'après ce que j'ai compris, c'est une nouvelle fonctionnalité (design by contract ?) qui vous oblige à utiliser la valeur de retour. Cela a du sens pour les fonctions controversées comme std::launder
(nodiscard depuis C++20), mais je me demande pourquoi std::move
n'est pas défini de la sorte en C++17/20. Connaissez-vous une bonne raison ou est-ce parce que C++20 n'est pas encore finalisé ?
Réponses
Trop de publicités?L'équipe de la bibliothèque standard de MSVC a ajouté plusieurs milliers d'instances de [[nodiscard]]
depuis VS 2017 15.6, et ont fait état d'un succès fou avec cette solution (à la fois en termes de découverte de nombreux bogues et d'absence de plaintes des utilisateurs). Les critères qu'ils ont décrits sont approximativement :
- Les purs observateurs, par exemple
vector::size()
,vector::empty
et mêmestd::count_if()
- Les choses qui acquièrent des ressources brutes, par ex.
allocate()
- Les fonctions pour lesquelles le rejet de la valeur de retour est extrêmement susceptible de conduire à un code incorrect, par ex.
std::remove()
MSVC marque les deux std::move()
y std::forward()
como [[nodiscard]]
en suivant ces critères.
Bien qu'il ne soit pas officiellement annoté en tant que tel dans la norme, il semble offrir un avantage clair pour l'utilisateur et il s'agit plutôt de concevoir un tel document afin de marquer toutes les bonnes choses. [[nodiscard]]
(encore une fois, plusieurs milliers d'instances de MSVC) et les appliquer - ce n'est pas un travail complexe en soi, mais le volume est important. Entre-temps, vous pouvez peut-être demander à votre fournisseur de bibliothèques standard préféré de [[nodiscard]]
beaucoup de choses ?
AFAIK P0600R1 est la seule proposition visant à ajouter [[nodiscard]]
à la bibliothèque standard qui a été appliquée à C++20. Extrait de ce document :
Nous suggérons une approche conservatrice :
[...]
Il ne doit pas être ajouté lorsque :
- [...]
- ne pas utiliser la valeur de retour n'a aucun sens mais ne fait pas de mal et n'est généralement pas une erreur
- [...]
Donc, [[nodiscard]] ne devrait pas signaler un mauvais code si ceci
- [...]
- ne fait pas mal et probablement aucun changement d'état n'a été signifié qui ne se produit pas
La raison en est que la bibliothèque standard utilise une approche conservatrice et qu'une approche plus agressive n'a pas encore été proposée.
1 votes
Je connais une raison qui me semble logique, mais à moins qu'un document officiel ne dise explicitement pourquoi ce n'est pas le cas, la question n'est plus qu'une question d'opinion.
0 votes
Pourquoi pensez-vous qu'il n'est pas nécessaire que std::move soit [[nodiscard]] ?
9 votes
Parce qu'il ne se passe absolument rien de mal (ou pas du tout) quand on ne l'utilise pas.
6 votes
@SebastianRedl : de la même manière, rien d'utile ne se produit. C'est la même chose que d'écrire une déclaration vide, donc
[[nodiscard]]
aiderait à diagnostiquer les bugs. De plus, rien de mauvais n'arrive quandvector::empty()
est ignoré, mais il est marqué[[nodiscard]]
pour des raisons évidentes.0 votes
Vous pourriez écrire et soumettre un document de proposition pour l'ajouter :)
6 votes
@SebastianRedl Ça semble être une bonne raison. à marquez-le
[[nodiscard]]
: "Hé, tu as fait quelque chose de complètement inutile. Tu voulais faire autre chose ?"0 votes
@SebastianRedl ce n'est pas tout à fait correct. Les objets sont dits être dans un état valide mais non spécifié et seul l'opérateur d'assignation pourrait être utilisé en toute sécurité sur eux. Donc ce n'est pas "rien de mauvais (ou du tout) ne se passe" à mon avis.
4 votes
@bbalchev
std::move
ne bouge pas. Faire passer un objet parstd::move
et ignorer le résultat n'apporte absolument rien.0 votes
Bien sûr, mais vous ne pouvez pas utiliser le paramètre que vous avez donné à
std::move
sauf pouroperator=
donc c'est toujours une erreur, n'est-ce pas ?0 votes
@bbalchev A séparé
std::move(x);
n'est pas une option.2 votes
@bbalchev Tous
std::move
renvoie une référence rvalue à l'objet ; de sorte que l'objet peut seront ensuite déplacés de si la référence est utilisée de cette façon.0 votes
Vous pourriez faire votre propre
bbalchev::move
qui a un[[nodiscard]]
sur elle. J'appellerais le mieneljay::move_dammit
mais c'est juste moi.0 votes
@GertArnold, je l'ai fait mais il est en attente d'examen.