How to make sure that a variable is not used

Viewed 142

Question

I have a function f taking some argument a, how can I make sure that the variable a is not used inside of the body, in the best case via a compile error? E.g., the following should not compile

void f( int & a ) {
    UNUSED( a );  // some magic rendering the variable a unusable
    ++a;
}

Story of the question:

In some of my functions, some variables are unused when compiled in release mode and are used in debug mode. Thus, to silence warnings I made myself an UNUSED( varname ) macro. But then, I realized that the proper name of the macro should be MAYBE_UNUSED( varname ).

Use case of UNUSED()

I have a set of implementations of a (hard to compute) function. The implementations shall all have the same signature, so they can easily be replaced with one another. But some implementations must not use certain input arguments. To make this explicit (for the reader and compiler) such UNUSED magic would be useful.

2 Answers

C++ allows you to have unnamed function parameters. It's exactly useful for situations where you do not intend on using the corresponding parameter, yet must declare it to match the signature e.g. when writing a callback to some library.

Simply redefine your function:

void f(int&) {
    // code ...
}

While @Jorengarenar's answer is probably what you want, the idea still interested me. Here's the closest I could do. It makes use of the fact that variables in a scope shadow variables in an outside scope with the same name. So here it is:

#define UNUSED(var_name) \
    class UnusedClass_ {} var_name

Well... that's pretty simple isn't it? However, it's the example of using this in a real function where you see the slight annoyance that is forced upon you:

#define UNUSED(var_name) \
    class UnusedClass_ {} var_name

void f(int &a)
{{
    UNUSED(a);
    ++a; // error: no match for 'operator++' (operand type is 'f(int&)::UnusedClass_')
}}

Notice the extra braces? You see, there has to be another scope where we create a new object of type UnusedClass_. Whenever we refer to a now, it's the UnusedClass_ a which shadows the int &a. We can't omit the braces; if we do, we'll get an error for redefining a. The way this actually works now is that UnusedClass_ is just an empty class, so no operators will work on it, and you probably can't put it in any function parameter (unless it's maybe some template function that does nothing with its parameter). In most cases, this should give an error. a; won't, and there's probably some way you can go out of your way to make this class/macro do something it isn't meant to do.

You could also place an empty statement with just the variable name to assert that the variable actually exists:

#define UNUSED(var_name) \
    (void) var_name;     \
    class UnusedClass_ {} var_name

void f(int &a)
{{
    UNUSED(b); // error: 'b' was not declared in this scope
}}

Is this the best solution? Probably not, and omitting the function name like in the other answer is probably a better idea. This is just a proof-of-concept of sorts, probably shouldn't be used in a real-life situation as there is probably some other alternative.

Related