11

Presently, I am using the following function template to suppress unused variable warnings:

template<typename T>
void
unused(T const &) {
  /* Do nothing. */
}

However, when porting to cygwin from Linux, I am now getting compiler errors on g++ 3.4.4 (On linux I am 3.4.6, so maybe this is a bug fix?):

Write.cpp: In member function `void* Write::initReadWrite()':
Write.cpp:516: error: invalid initialization of reference of type 'const volatile bool&' from expression of type 'volatile bool'
../../src/common/Assert.h:27: error: in passing argument 1 of `void unused(const T&) [with T = volatile bool]'
make[1]: *** [ARCH.cygwin/release/Write.o] Error 1

The argument to unused is a member variable declared as:

  volatile bool readWriteActivated;

Is this a compiler bug or a bug in my code?

Here is the minimal test case:

template<typename T>
void unused(T const &) { }

int main() {
  volatile bool x = false;
  unused(!x); // type of "!x" is bool
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
WilliamKF
  • 41,123
  • 68
  • 193
  • 295

5 Answers5

29

The actual way of indicating you don't actually use a parameter is not giving it a name:

int f(int a, float) {
     return a*2;
}

will compile everywhere with all warnings turned on, without warning about the unused float. Even if the argument does have a name in the prototype (e.g. int f(int a, float f);), it still won't complain.

emvee
  • 4,371
  • 23
  • 23
  • 9
    Yes, and I normally use something like int f(int count, float /*epsilon*/ ) in order to name the unused parameter and its meaning. – ur. Dec 15 '09 at 09:36
  • Indeed ur, that's good manners, I forgot that, but you're absolutely right. – emvee Dec 15 '09 at 09:38
  • 4
    This is not what the question is asking. Omitting variable name for function arg works great, but here the variable is declared inside the function, and thus cannot be omitted. Further in this case, the variable name is needed since it is used in some #ifdef cases and the unused is for the else so that no warning is generated. – WilliamKF Dec 16 '09 at 01:42
  • If you don't use it, don't declare it. Even simpler! – emvee Dec 16 '09 at 10:24
  • 1
    The problem with not naming parameters is that you might need to inspect them later on. When you try to see their values in the debugger, you'll wish you had given them names. – Timothy003 Aug 25 '11 at 18:56
  • 1
    If they're unused there's not much to inspect in the debugger. – emvee Mar 30 '12 at 22:25
9

I'm not 100% sure that this is portable, but this is the idiom I've usually used for suppressing warnings about unused variables. The context here is a signal handler that is only used to catch SIGINT and SIGTERM, so if the function is ever called I know it's time for the program to exit.

volatile bool app_killed = false;
int signal_handler(int signum)
{
    (void)signum; // this suppresses the warnings
    app_killed = true;
}

I tend to dislike cluttering up the parameter list with __attribute__((unused)), since the cast-to-void trick works without resorting to macros for Visual C++.

Tom
  • 10,689
  • 4
  • 41
  • 50
  • Yes, it's both legal C++ and portable. – greyfade Dec 15 '09 at 06:09
  • 1
    If you want to make this approach compatible with the existing code that uses unused(), define a macro: `#define unused(x) ((void)x)` – Martin B Dec 25 '09 at 09:45
  • This won't work if the variable is a reference to an incomplete type. E.g., `struct a; void f(a &a_) { (void)a_; }` will give a compile error. – Timothy003 Aug 25 '11 at 18:19
  • if you didn't need to use to signum, what if you just made it an unnamed parameter... like this: `int signal_handler(int)` It will fit the same prototype, and possibly even save some memory –  Feb 27 '13 at 21:50
4

It is a compiler bug and there are no known work arounds:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42655

It is fixed in v4.4.

WilliamKF
  • 41,123
  • 68
  • 193
  • 295
2

In GCC, you can define a macro as follows:

#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#elif defined(__LCLINT__)
# define UNUSED(x) /*@unused@*/ x
#else
# define UNUSED(x) x
#endif 

Any parameters marked with this macro will suppress the unused warning GCC emits (and renames the parameter with a prefix of UNUSED_). For Visual Studio, you can suppress warnings with a #pragma directive.

greyfade
  • 24,948
  • 7
  • 64
  • 80
  • Yes, but this is compiler dependent. The question gives the common way to do this in a non-compiler dependent fashion, however, as shown, it is exercising a bug in the compiler. – WilliamKF Dec 16 '09 at 01:49
  • +1 this is the most portable answer. also, gcc supports `#pragma unused` -- see also the documentation for the `_Pragma` directive. – justin Oct 06 '10 at 17:26
2

The answer proposed by haavee (amended by ur) is the one I would normally use:

int f(int a, float /*epsilon*/) {
     return a*2;
}

The real problem happens when the argument is sometimes but not always used in the method, e.g.:

int f(int a, float epsilon) {
#ifdef LOGGING_ENABLED
     LOG("f: a = %d, epsilon = %f\n", a, epsilon);
#endif
     return a*2;
}

Now, I can't comment out the parameter name epsilon because that will break my logging build (I don't want to insert another #ifdef in the argument list because that makes the code much harder to read).

So I think the best solution would be to use Tom's suggestion:

int f(int a, float epsilon) {
(void) epsilon;    // suppress compiler warning for possibly unused arg
#ifdef LOGGING_ENABLED
     LOG("f: a = %d, epsilon = %f\n", a, epsilon);
#endif
     return a*2;
}

My only worry would be that some compilers might warn about the "(void) epsilon;" statement, e.g. "statement has no effect" warning or some such - I guess I'll just have to test on all the compilers I'm likely to use...

JohnAndy
  • 21
  • 3