Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to ignore [[nodiscard]] in a special case?

C++17 has a new attribute, [[nodiscard]].

Suppose, that I have a Result struct, which has this attribute:

struct [[nodiscard]] Result {
};

Now, if I call a function which returns Result, I got a warning if I don't check the returned Result:

Result someFunction();

int main() {
    someFunction(); // warning here, as I don't check someFunction's return value
}

This program generates:

warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]

So far, so good. Now suppose, that I have a special function, for which I still want to return Result, but I don't want this warning generated, if the check is omitted:

Result someNonCriticalFunction();

int main() {
    someNonCriticalFunction(); // I don't want to generate a warning here
}

It is because, someNonCriticalFunction() does something non-critical (for example, something like printf - I bet that no-one checks printf's return value all the time); most cases, I don't care if it fails. But I still want it to return Result, as in some rare cases, I do need its Result.

Is it possible to do this somehow?


Possible solutions which I don't like:

  • I would not like calling it as (void)someNonCriticalFunction(), because this function is called a lot of times, it is awkward
  • creating a wrapper around someNonCriticalFunction(), which calls (void)someNonCriticalFunction(): I don't want to have a differently named function just because of this
  • removing [[nodiscard]] from Result, and add it to every function which returns Result
like image 283
geza Avatar asked Nov 03 '17 21:11

geza


People also ask

Should I use [[ Nodiscard ]]?

It is never necessary to add the [[nodiscard]] attribute. From 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.

What is Nodiscard C++?

C++17. The [[nodiscard]] attribute can be used to indicate that the return value of a function shouldn't be ignored when you do a function call. If the return value is ignored, the compiler should give a warning on this.


2 Answers

Why not make use of std::ignore from the <tuple> header—that would make the discard explicit:

[[nodiscard]] int MyFunction() { return 42; }

int main() 
{
    std::ignore = MyFunction();
    return 0;
}
  • Compiler explorer of this code snippet: https://godbolt.org/z/eGPsjajz8
  • CPP Reference for std::ignore: https://en.cppreference.com/w/cpp/utility/tuple/ignore
like image 144
Johann Studanski Avatar answered Oct 12 '22 01:10

Johann Studanski


They say that every problem in computer science can be solved by adding another layer of indirection:

template <bool nodiscard=true>
struct Result;

template <>
struct Result<false> {
    // the actual implementation
};

template <>
struct [[nodiscard]] Result<true>
    : Result<false>
{
    using Result<false>::Result;
};

This is effectively making Result conditionally [[nodiscard]], which allows:

Result<true> someFunction();
Result<false> someNonCriticalFunction();

int main() {
    someFunction();            // warning here
    someNonCriticalFunction(); // no warning here
}

Although really, this is identical to:

  • removing [[nodiscard]] from Result, and add it to every function which returns Result

which gets my vote to begin with.

like image 24
Barry Avatar answered Oct 12 '22 00:10

Barry