在C ++中禁止使用未使用的变量警告=>编译器错误或代码错误?

时间:2009-12-15 04:49:30

标签: c++ templates language-lawyer member-variables

目前,我使用以下函数模板来抑制未使用的变量警告:

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

然而,当从Linux移植到cygwin时,我现在在g ++ 3.4.4上遇到编译错误(在linux上我是3.4.6,所以这可能是一个bug修复?):

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

未使用的参数是声明为:

的成员变量
  volatile bool readWriteActivated;

这是编译器错误还是代码中的错误?

这是最小的测试用例:

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

int main() {
  volatile bool x = false;
  unused(!x); // type of "!x" is bool
}

5 个答案:

答案 0 :(得分:28)

指示您实际上不使用参数的实际方法是不给它起一个名字:

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

将在所有警告都打开的情况下编译,而不会对未使用的浮点数发出警告。即使参数确实在原型中有一个名称(例如int f(int a, float f);),它仍然不会抱怨。

答案 1 :(得分:9)

我不是100%确定这是可移植的,但这是我通常用来抑制有关未使用变量的警告的习惯用法。这里的上下文是一个信号处理程序,仅用于捕获SIGINTSIGTERM,所以如果调用该函数,我知道程序退出的时间。

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

我倾向于不喜欢使用__attribute__((unused))来混淆参数列表,因为无需借助Visual C ++的宏就可以使用强制转换技巧。

答案 2 :(得分:4)

这是一个编译器错误,并且没有已知的解决方法:

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

在v4.4中已修复。

答案 3 :(得分:2)

在GCC中,您可以按如下方式定义宏:

#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 

使用此宏标记的任何参数都将禁止GCC发出未使用的警告(并使用前缀UNUSED_重命名参数)。对于Visual Studio,您可以使用#pragma指令禁止警告。

答案 4 :(得分:1)

haavee提出的答案(由你修改)是我通常会使用的答案:

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

当参数有时但在方法中并不总是使用时,会出现真正的问题,例如:

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

现在,我无法注释掉参数名称epsilon,因为这会破坏我的日志记录构建(我不想在参数列表中插入另一个#ifdef,因为这会使代码更难阅读)。

所以我认为最好的解决方案是使用Tom的建议:

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;
}

我唯一担心的是一些编译器可能会警告“(void)epsilon”;声明,例如“声明没有效果”警告或其他一些 - 我想我只需要测试我可能会使用的所有编译器......