Advertisement

[[nodiscard]] on operators?

Started by June 18, 2023 05:59 AM
5 comments, last by Juliean 1 year, 5 months ago

Hi everybody,

[[nodiscard]] is well used on functions.

What about operator [], <, ≤, >, ≥= == and !=?

Of course you would want to use it on operators as well. There is no reason why you can't and shouldn't, what makes you doubt whether to use it there?

Advertisement

I don't think I've ever accidentally discarded the result of an operator expression, so I don't think it's important to use [[nodiscard]] there. Statements like f(); look natural because f could be a function that returns void, but statements like a + b; immediately stand out as weird. That said, there's no compelling reason not to use [[nodiscard]] on operator overload functions. Operator overloads functions are just functions, after all.

Because it looks like the C++ STD is not using at all there… maybe they have special rules on their side?

It was added to the allocation functions, which makes sense as it is a guaranteed bug to not capture the results of an allocating new. Miss it and you have a guaranteed memory leak.

It was also added to one other that was the cause of countless bugs, empty() which is a query people often mistake for clear() which is a command, but allocation was the compelling reason.

The same is not true of the operators you mentioned. You can compare values, do nothing with it, and have no consequences. It is neutral, basically a nop or dead code, rather than a guaranteed bug. It is a little weird, but still defined behavior.

I would say to add it to your own allocating functions, for the same reason. Anything with a “source and sink” model, allocating in one place and requiring deallocation elsewhere, seems a better use.

frob said:
The same is not true of the operators you mentioned. You can compare values, do nothing with it, and have no consequences. It is neutral, basically a nop or dead code, rather than a guaranteed bug. It is a little weird, but still defined behavior.

Well, outside of the egregious example of having a badly named function like “empty" which could consufe people in what to do; I don't think there is a difference for a (const) function that queries a value VS an operator, in regards to nodiscard. Calling any well-named function that only returns a value without modifying any state is inheritely consequence-free in that nothing breaks by doing it, however I might ask the question - what is the actual use-case of having such a function (or operator) without using its return-value? If the function does nothing but return a value, if you don't use the value, in my mind that is 99.9% a bug. For example:

object.complex == value;

Here, I meant to type “=” but instead typed “==”. With nodiscard, this error is caught directly by the compiler, otherwise, this is the type of error that in a large-codebase might show up with some static code analysis tool.

Maybe that a matter of definition, but again, I don't consider [[nodiscard]] a bandaid-fix for bad naming of functions, or noticable bugs like allocation-leaks, but instead as a general protection of calling a side-effect free function (including operators) accedentially without consuming its return (so a general protection for unintended usage). You can always “(void)call()” if you really have a valid case for discarding the return.

This topic is closed to new replies.

Advertisement