Why is std::move not [[nodiscard]] in C++20?
I've recently read about [[nodiscard]]
in C++17, and as far as I understand it's a new feature (design by contract?) which forces you to use the return value. This makes sense for controversial functions like std::launder
(nodiscard since C++20), but I wonder why std::move
isn't defined like so in C++17/20. Do you know a good reason or is it because C++20 isn't finalised yet?
Solution 1:
The MSVC standard library team went ahead and added several thousand instances of [[nodiscard]]
since VS 2017 15.6, and have reported wild success with it (both in terms of finding lots of bugs and generating no user complaints). The criteria they described were approximately:
- Pure observers, e.g.
vector::size()
,vector::empty
, and evenstd::count_if()
- Things that acquire raw resources, e.g.
allocate()
- Functions where discarding the return value is extremely likely to lead to incorrect code, e.g.
std::remove()
MSVC does mark both std::move()
and std::forward()
as [[nodiscard]]
following these criteria.
While it's not officially annotated as such in the standard, it seems to provide clear user benefit and it's more a question of crafting such a paper to mark all the right things [[nodiscard]]
(again, several thousand instances from MSVC) and apply them -- it's not complex work per se, but the volume is large. In the meantime, maybe prod your favorite standard library vendor and ask them to [[nodiscard]]
lots of stuff?
Solution 2:
AFAIK P0600R1 is the only proposal for adding [[nodiscard]]
to the standard library that was applied to C++20. From that paper:
We suggest a conservative approach:
[...]
It should not be added when:
- [...]
- not using the return value makes no sense but doesn’t hurt and is usually not an error
- [...]
So, [[nodiscard]] should not signal bad code if this
- [...]
- doesn’t hurt and probably no state change was meant that doesn’t happen
So the reason is that the standard library uses a conservative approach and a more aggresive one is not yet proposed.