On a purely practical level, I have deal with this daily. The best solution to date is to use the pre-processor. My common header file contains:
//-------------------------------------------------------------------------
// Suppress nuisance compiler warnings. Yes, each compiler can already
// do this, each differently! VC9 has its UNREFERENCED_PARAMETER(),
// which is almost the same as the SUPPRESS_UNUSED_WARNING() below.
//
// We append _UNUSED to the variable name, because the dumb gcc compiler
// doesn't bother to tell you if you erroneously _use_ something flagged
// with __attribute__((unused)). So we are forced to *mangle* the name.
//-------------------------------------------------------------------------
#if defined(__cplusplus)
#define UNUSED(x) // = nothing
#elif defined(__GNUC__)
#define UNUSED(x) x##_UNUSED __attribute__((unused))
#else
#define UNUSED(x) x##_UNUSED
#endif
An example of the use of UNUSED is:
void foo(int UNUSED(bar)) {}
Sometimes you actually need to refer to the parameter, for example in an assert() or debug statement. You can do so via:
#define USED_UNUSED(x) x##_UNUSED // for assert(), debug, etc
Also, the following are useful:
#define UNUSED_FUNCTION(x) inline static x##_UNUSED // "inline" for GCC warning
#define SUPPRESS_UNUSED_WARNING(x) (void)(x) // cf. MSVC UNREFERENCED_PARAMETER
Examples:
UNUSED_FUNCTION(int myFunction)(int myArg) { ...etc... }
and:
void foo(int bar) {
#ifdef XXX
// ... (some code using bar)
#else
SUPPRESS_UNUSED_WARNING(bar);
#endif
}