this post was submitted on 30 Nov 2024
1 points (66.7% liked)
C++
1805 readers
2 users here now
The center for all discussion and news regarding C++.
Rules
- Respect instance rules.
- Don't be a jerk.
- Please keep all posts related to C++.
founded 2 years ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
view the rest of the comments
When would this actually be necessary? Realistically, I see two possibilities.
1 - The function's purpose is to generate a result value, meaning that ignoring the result is a waste of a function call and any resources consumed by the function. In this case, though, nobody would ever be calling the function unless they specifically wanted the result.
2 - The caller must take ownership of the result. In this case, just don't return raw pointers.
The addition of [[nodiscard]] suggests that there are valid reasons, but I have never personally come across one.
Consider, say, the
printf
family of functions. The side-effect of their invocation is quite notorious and clear: print something to the screen, or write it to a file, etc. This kind of thing is not expressable (and should not be expressed as) as a return type. But these functions do have a return value: a status code indicating whether the write-to-medium was successful or else why. It's so easy to discard this information and end up eg.: ignorin a write that didn't happen because there was not enough room, or writing more bytes than the destination buffer could afford to take (hellooooo, buffer overflow!).There are lots of functions (probably entire categories, but I'm not that strong on type theory) where the "result" is vastly different from the "return" or can not be expressed as such. Foremost cases I can come up with are I/O, stuff on complex types where types also represent actions or components with side effects (eg.: GUIs), and pretty much anything about inserting or removing elements from containers. In those cases, if the two things differ but the return is also important, it'd be nice to have a mechanism to make sure that it can't be accidentally ignored (explicit, intentional ignoring is fine; that's what we have
(void)(expr...)
in the language).Another reason for having this capability is having a function with a composite return-result type, such as a
std::expected<T,E>
where you want to help make sure the composition is handled correctly by the caller.