[[nodiscard]] serves as a warning to the compiler and, subsequently, to developers, indicating that the return value of that function is important and should be used or captured.
What are the common practices and considerations (to detect possible bugs at early stage): To apply [[nodiscard]] attribute to any member function that returns a value (except special cases)? ...Or to apply it only to member functions that it is necessary (for example: a member function that returns a memory allocation)?
When to apply
[[nodiscard]]is opinionated.Minimal Approch
The most minimal approach is to only apply it when a function is unusable with the result discarded, and when the user is likely to misuse it without the attribute. This is what the C++ standard library does. For example,
std::vector::empty()is marked[[nodiscard]]because it could mean:To name another example,
std::launderis marked[[nodiscard]]because people commonly assume that it somehow changes the pointer, and they don't need to use the result.[[nodiscard]]is only used in the standard to prevent such misconceptions and very likely mistakes.Maximal Approach
The most maximal approach is to apply
[[nodiscard]]whenever a function isn't correctly usable with the result discarded. For example,std::maxis pointless if you discard the result, and standard library implementations are free to make it[[nodiscard]].std::vector::size()could also be made[[nodiscard]]by that standard. In fact, most non-void functions could be(1).Clang-Tidy Approach
You can also stick to the clang-tidy
modernize-use-nodiscardrule, which recommends[[nodiscard]]if all of the following conditions are met:This is obviously quite a long list and fairly pessimistic, but it's a decent starting point and can be automated.
Conclusion
You'll have to decide for yourself which approach to choose. There is no official guideline(2). If you don't care about the added verbosity of
[[nodiscard]]on a huge amount of functions, it's perfectly fine to use the maximal approach. The more[[nodiscard]]attributes you correctly use, the more bugs you are able to prevent.(1) Most, but not all. For example,
operator<<overloads for stream insertion should not be[[nodiscard]]because discarding the resulting stream is common practice. The same applies tooperator=overloads.(2) CppCoreGuidelines also hasn't decided on a recommendation. There is consensus that there should be some guideline for
[[nodiscard]], but the discussion got tied up in specifics, and people lost interest in the subject.