c++gccc++14

Is it ok to use std::ignore in order to discard a return value of a function to avoid any related compiler warnings?


I know that you can use static_cast<void>, but it just seems too verbose for me, and not reflecting the original intent that I want to discard a return value, not to cast it to anything.

Recently I stumbled upon std::ignore, which can accept a value of any type, the name is clear and readable, and to me it seems fitting.

I know that the initial intent was to use std::ignore alongside with std::tie to discard any unwanted values, but I guess the original intent of static_cast was to actually cast values for some better reasons than discarding values so the compiler won't complain.

So, is it OK to use std::ignore for the purpose I described in the question?

For example:

std::ignore = std::transform(...);

Solution

  • Using std::ignore outside of std::tie is supported since C++26 (see P2968: Make std::ignore a first-class object). Even before it was officially supported, it was considered much better style by some people.

    Never cast to (void) to ignore a [[nodiscard]] return value. If you deliberately want to discard such a result, first think hard about whether that is really a good idea (there is usually a good reason the author of the function or of the return type used [[nodiscard]] in the first place). If you still think it’s appropriate and your code reviewer agrees, use std::ignore = to turn off the warning which is simple, portable, and easy to grep.

    - CppCoreGuidelines ES.48: Avoid casts

    Note: Herb Sutter committed the guideline. With the std::ignore rule, you can consistently teach not to use casts, and don't have to make an exception for casting to void.

    Historical note on C++23 and older

    An argument against std::ignore is that it used to be only defined in terms of its effect in std::tie:

    template<class... TTypes>
    constexpr tuple<TTypes&...> tie(TTypes&... t) noexcept;
    

    Returns: tuple<TTypes&...>(t...). When an argument in t is ignore, assigning any value to the corresponding tuple element has no effect.

    - [utilities] std::tie

    This is mostly a philosophical issue though. In every major standard library, std::ignore has been implemented in such a way that you can do std::ignore = ... on its own.

    Conclusion

    In the end, it's stylistic preference. You can use (void), static_cast<void>, or std::ignore. They are all acceptable, and which one to use is a matter of opinion. What matters is that you use a consistent style throughout your project, i.e. if you use std::ignore to discard results in one place, use it everywhere.