Ответ 1
Это ошибка компилятора, и нет известных работ вокруг:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42655
Это исправлено в версии 4.4.
В настоящее время я использую следующий шаблон функции для подавления предупреждений о неиспользуемых переменных:
template<typename T>
void
unused(T const &) {
/* Do nothing. */
}
Однако при переносе на cygwin из Linux я теперь получаю ошибки компилятора в g++ 3.4.4 (On linux я 3.4.6, так что, возможно, это исправление ошибки?):
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
Аргумент для unused - это переменная-член, объявленная как:
volatile bool readWriteActivated;
Является ли это ошибкой компилятора или ошибкой в моем коде?
Вот минимальный тестовый пример:
template<typename T>
void unused(T const &) { }
int main() {
volatile bool x = false;
unused(!x); // type of "!x" is bool
}
Это ошибка компилятора, и нет известных работ вокруг:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42655
Это исправлено в версии 4.4.
Фактический способ указания того, что вы фактически не используете параметр, не дает ему имени:
int f(int a, float) {
return a*2;
}
будет компилироваться повсюду с включенными предупреждениями, без предупреждения о неиспользуемом поплавке. Даже если аргумент имеет имя в прототипе (например, int f(int a, float f);
), он все равно не будет жаловаться.
Я не уверен на 100%, что это переносимо, но это идиома, которую я обычно использовал для подавления предупреждений о неиспользуемых переменных. Контекст здесь - обработчик сигналов, который используется только для ловли SIGINT
и SIGTERM
, поэтому, если функция когда-либо называется, я знаю, что время для выхода программы.
volatile bool app_killed = false;
int signal_handler(int signum)
{
(void)signum; // this suppresses the warnings
app_killed = true;
}
Мне не нравится заполнять список параметров с помощью __attribute__((unused))
, так как трюк cast-to-void работает, не прибегая к макросам для Visual С++.
В GCC вы можете определить макрос следующим образом:
#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#elif defined(__LCLINT__)
# define UNUSED(x) /*@[email protected]*/ x
#else
# define UNUSED(x) x
#endif
Любые параметры, отмеченные этим макросом, подавляют неиспользуемое предупреждение GCC испускает (и переименовывает параметр с префиксом UNUSED_
). Для Visual Studio вы можете подавлять предупреждения с помощью директивы #pragma
.
Ответ, предложенный haavee (измененный ur), является тем, который я обычно использовал:
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";. "выражение не имеет эффекта" или некоторые такие - я думаю, мне просто нужно будет проверить все компиляторы, которые я, вероятно, буду использовать...