Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Explanation of [[nodiscard]] in C++17

In a project using C++20, CLion suggested me to add [[nodiscard]] to my const class method definitions, e.g.,

class Test {
public:
    [[nodiscard]] int f(int a, int b) const {
        return a + b;
    }
}

The explanation is

Adds [[nodiscard]] attributes (introduced in C++17) to member functions in order to highlight at compile time which return values should not be ignored.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

and I also checked cppreference.com:

If a function declared nodiscard or a function returning an enumeration or class declared nodiscard by value is called from a discarded-value expression other than a cast to void, the compiler is encouraged to issue a warning.

Appears in a function declaration, enumeration declaration, or class declaration.

If, from a discarded-value expression other than a cast to void,

  • a function declared nodiscard is called, or
  • a function returning an enumeration or class declared nodiscard by value is called, or
  • a constructor declared nodiscard is called by explicit type conversion or static_cast, or
  • an object of an enumeration or class type declared nodiscard is initialized by explicit type conversion or static_cast,

the compiler is encouraged to issue a warning.

I honestly don’t really understand why this annotation is needed in this location. Why would the compiler ignore my return values if the caller processes them further? Is there an intuitive explanation of what it tells the compiler exactly and why it’s needed?

>Solution :

The idea is that if it only makes sense to call your function when you also take its return value, calling it without taking the return value is a programming error. The annotation [[nodiscard]] helps programmers interfacing with your code avoid this error.

In your specific example, your function computes a result without side effects, so the static code analyzer realizes that it would be a good fit for [[nodiscard]]. For example:

Test a;
auto x = a.f(1, 2); // ok
std::cout << "For 1, 2 we get " << a.f(1,2) << std::endl; // also ok
a.f(1, 2); // warning here

Here the compiler is encouraged to warn in the last line about the function call without further processing of the result.

Discussion

An example of good use for [[discard]] can be object methods that manipulate an object, but provide the result in a copy. Example:

DateTime yesterday = DateTime.now().substractOneDay();
std::cout << "Yesterday was " << yesterday.nameOfDay() << std::endl;

vs:

DateTime yesterday = DateTime.now();
yesterday.substractOneDay();
std::cout << "Yesterday was " << yesterday.nameOfDay() << std::endl;

A [[nodiscard]] would tell the programmer of the second example, that they are using it wrong.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading