Home > Back-end >  Why is the [[nodiscard]] attribute not transitive?
Why is the [[nodiscard]] attribute not transitive?

Time:09-04

Consider the following code:

[[nodiscard]] float val() { return 3.; }
float junk() { return val(); }
int main() { junk(); }

It seems logical that junk should be required to be marked as [[nodiscard]], yet the above example compiles without any warnings.

Put differently, what is the point of val being no discard, if its return value can be returned from a "discardable" function?

CodePudding user response:

[[nodiscard]] merely prevents the value returned from val to be discarded. junk is using the returned value so all is ok. If you want you can mark junk as [[nodiscard]].

Moreover, note that there is no strong guarantee to get a warning in the first place (cppreference):

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.

The way to achieve the behavior you want is to use a custom class that is specified as [[nodiscard]]:

#include <iostream>

struct [[nodiscard]] foo {};

foo val() { return {};}
foo junk() { return val(); }

int main() {
    junk();
}

Gcc reports:

<source>:9:5: error: ignoring return value of function declared with 'nodiscard' attribute [-Werror,-Wunused-result]
    junk();
    ^~~~
  •  Tags:  
  • c
  • Related