views:

1740

answers:

5

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
}
+1  A: 

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
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
+1 this is the most portable answer. also, gcc supports `#pragma unused` -- see also the documentation for the `_Pragma` directive.
Justin
+4  A: 

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
Yes, it's both legal C++ and portable.
greyfade
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
+7  A: 

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.

haavee
+1, this is the proper way to do it.
mizipzor
Yes, and I normally use something like int f(int count, float /*epsilon*/ ) in order to name the unused parameter and its meaning.
ur
Indeed ur, that's good manners, I forgot that, but you're absolutely right.
haavee
+1. Together with ur's suggestion, the cleanest and most expressive way to do it.
DevSolar
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
If you don't use it, don't declare it. Even simpler!
haavee
+2  A: 

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

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

WilliamKF
A: 

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