std::ignore for ignoring unused variable

24.2k Views Asked by At

Is it a good approach to use std::ignore for ignoring unused variables?

Suppose I have a function like this:

void func(int i)
{
   //for some reason, I don't need i anymore but I cannot change signature of function    
   std::ignore = i; 
}

Additional Info

This was one example and some answers suggested to use anonymous variables. But how would I do it for other cases, like:

int Thread_UnSafe_func_returnSomething():
void func()
{
   // To make it thread safe
   // Also it is required to call only once
   static int i = Thread_UnSafe_func_returnSomething();

   std::ignore = i;
}
7

There are 7 best solutions below

7
Hayt On BEST ANSWER

std::ignore may work but it is intended to be used for tuples. So you need to include the tuple header and who knows what operations are done for the assignment. This also may break in another c++ version because it was never documented to be used that way.

A better way for this is the C++17 attribute [[maybe_unused]]

void func([[maybe_unused]] int i)
{
}

It places the declaration right at the variable declaration, so you don't have to declare it in an extra line/statement.

The same can be used for local (and local-static) variables

...
[[maybe_unused]] static int a = something();
...

And also for many more:

Appears in the declaration of a class, a typedef­, a variable, a non­static data member, a function, an enumeration, or an enumerator. If the compiler issues warnings on unused entities, that warning is suppressed for any entity declared maybe_unused.

See http://en.cppreference.com/w/cpp/language/attributes

As for the people concerned that you can still use the variables after you declare them unused:

Yes, this is possible but (at least with clang) you will get warnings in case you use maybe_unused declared variables.

0
gsamaras On

std::ignore was not intended to be used for this purpose:

An object of unspecified type such that any value can be assigned to it with no effect. Intended for use with std::tie when unpacking a std::tuple, as a placeholder for the arguments that are not used.


I would suggest you not do what you are thinking, since in a real-world big project, it will lead to code that is harder to maintain, where one would look at the prototype of a function, would see that it takes an argument int i, but the function would not need that in reality - doesn't feel nice, does it? :)

8
Alexey Guseynov On

In such case just don't write variable name:

void func(int /*i*/)
{
    ...
}

@Hayt's answer is good, but uses latest version of C++ which is not always available. Not writing variable name is an old convention to tell a compiler that you don't actually need the variable.

For an updated question I would go for a static instance of a class with needed initialization in a constructor. I say initialization because the only reason I can make for having such function is to initialize some global object.

class SomethingInitializer {
public:
    SomethingInitializer() {
        func_returnSomething();
    }
    ~SomethingInitializer() {
        // Note, that when you initialize something it is a good practice to deinitialize it at the end, and here is a proper place for that.
    }
};

void func() {
    static SomethingInitializer initializer;
}

This solution has a small bonus: SomethingInitializer is RAII compliant. So when application terminates destructor is called and it can make deinitialization.

Note, that compiler knows that classes may do something useful in constructor and destructor, so it will not complain for unused variable.

4
Jarod42 On

In C++17, attribute [[maybe_unused]] might be used:

void func([[maybe_unused]]int i)
{
    // ...
}

Previously, as alternative, without removing i from signature (as some documentation tools may require it), there are several ways to silence the warning:

  • casting to void:

    void func(int i)
    {
       static_cast<void>(i); // Silence warning for unused variable
    }
    

    It is not fully portable, but that suppresses the warning on most compilers.

  • The "clean" way is to create a dedicated function for that:

    template <typename T>
    void Unused(T&& /*No name*/) { /*Empty*/ }
    

    and then

    void func(int i)
    {
       Unused(i); // Silence warning for unused variable
    }
    
0
skypjack On

Another way to do that is by means of a trailing return type as the following one:

auto func(int i) -> decltype(void(i)) {}
int main() {}

If you have more than one variable, you can list them all:

auto func(int i, int j) -> decltype(void(i), void(j)) {}
int main() {}

And you can still declare your preferred return type if void is not what you want:

auto func(int i) -> decltype(void(i), int{}) { return 42; }
int main() {}

The advantages of this solution are:

  • Variable name is preserved: as mentioned by others, do not give a name to the variable could not be an option (because of your documentation system, as an example).

  • You won't pollute your function body with useless expressions aimed to silent a few warnings.

  • You don't have to explicitly define support function to do that.

Of course, this doesn't apply to static variables declared in the function body, but you can do something similar when returning from the function (just an example):

int f() {
    static int i = 0;
    static int j = 0;
    return void(i), void(j), 42;
}

int main () {}

More ore less the same advantages.

2
Jacob Manaker On

I think you have an XY problem here. You don't really care about how to ignore static variables; you just want to call a function once (and only once) in a thread-safe, reentrant manner.

To which I say: have you heard of std::call_once? You should rewrite your method as

#include <mutex>

int Thread_UnSafe_func_returnSomething();
void func(void)
{
      //To make it thread safe
     static std::once_flag initComplete;
     std::call_once(initComplete, func_returnSomething);
 }
0
Don On

I would like to suggest an alternative for those compiling with ARM.

You can use the _attribute_ keyword to assign the "unused" attribute to a variable. Doing so will cause the compiler to not generate any warnings if the variable is not referenced.

You can assign the "unused" attribute to a method parameter in the method declaration. Simply place the attribute keyword immediately following the variable's name along with the "unused" attribute. I have provided an example below.

Example:

void someFunc(int x __attribute__((unused)) );

The documentation can be referenced here.