Nodiscard is a way of “enforcing” a contract with the user about how your code needs to be used in order to avoid undefined behaviour.
(I say “enforcing” in quotes because, instead of being an actual constraint, it’s merely an attribute - so a conforming compiler can happily ignore it)
Here are two examples of where it is useful:
- Returning a success code that must be checked before proceeding with an operation that could have bad consequences if the previous operation failed. Unchecked operations are one of the major sources of bugs in the wild, so no discard at least points the user to the potential problem.
- Returning something that doesn’t make any sense to immediately discard. This is usually down to a mistake - such as calling vector::empty thinking that it’s going to clear the vector, when it actually returns a bool telling you if it’s empty or not (an awful name, but then so is vector…). It makes no sense to check if it’s empty without using that result, so the warning indicates that the user has made a mistake.
Using it to enforce that every return value is handled is stupid as it can lead to error blindness and you’ll ignore it when you actually need it.
The function is entirely useless and pointless to call without using the returned value, and [[nodiscard]] pointed this out to me. Perfect.
I know there are a lot of people out there still writing C and I've come to accept that I will never understand or agree with those people, but to be writing C++ and passing raw pointers around in 2023 is a hell of a choice IMO.