Как лучше всего отключить предупреждение о неиспользуемых переменных?

У меня есть кросс-платформенное приложение, и в нескольких моих функциях используются не все значения, переданные в функции. Поэтому я получаю предупреждение от GCC о том, что существуют неиспользуемые переменные.

Каким будет лучший способ кодирования вокруг предупреждения?

#ifdef вокруг функции?

#ifdef _MSC_VER
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal qrLeft, qreal qrTop, qreal qrWidth, qreal qrHeight)
#else
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal /*qrLeft*/, qreal /*qrTop*/, qreal /*qrWidth*/, qreal /*qrHeight*/)
#endif
{

Это так уродливо, но похоже на то, как предпочтет компилятор.

Или назначить ноль переменной в конце функции? (который я ненавижу, потому что он меняет что-то в потоке программы, чтобы отключить предупреждение компилятора).

Есть ли правильный способ?

Ответ 1

Вы можете поместить его в выражение "(void)var;" (ничего не делает), чтобы компилятор увидел, что он используется. Это переносимо между компиляторами.

например.

void foo(int param1, int param2)
{
    (void)param2;
    bar(param1);
}

Или

#define UNUSED(expr) do { (void)(expr); } while (0)
...

void foo(int param1, int param2)
{
    UNUSED(param2);
    bar(param1);
}

Ответ 2

В GCC и Clang вы можете использовать директиву препроцессора __attribute__((unused)) для достижения своей цели.
Например:

int foo (__attribute__((unused)) int bar) {
   return 0;
}

Ответ 3

Ваше текущее решение лучше всего - закомментируйте имя параметра, если вы его не используете. Это относится ко всем компиляторам, поэтому вам не нужно использовать предварительный процессор, чтобы делать это специально для GCC.

Ответ 5

Сотрудник просто указал мне на этот красивый маленький макрос здесь

Для удобства я включу макрос ниже.

#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

void dcc_mon_siginfo_handler(int UNUSED(whatsig))

Ответ 6

не помечает эти предупреждения по умолчанию. Это предупреждение должно быть включено либо явно, передавая -Wunused-parameter компилятору, либо неявно, передавая -Wall -Wextra (или, возможно, некоторую другую комбинацию флагов).

Предупреждения о неиспользованных параметрах можно просто подавить, передав -Wno-unused-parameter компилятору, но учтите, что этот флаг отключения должен идти после любых возможных флагов включения этого предупреждения в командной строке компилятора, чтобы оно могло вступить в силу.

Ответ 7

Еще более чистый способ - просто прокомментировать имена переменных:

int main(int /* argc */, char const** /* argv */) {
  return 0;
}

Ответ 8

Обновление С++ 17

В С++ 17 мы получаем атрибут [[Maybe_unused]], который описан в [dcl.attr.unused]

Атрибут-маркер Maybe_unused указывает, что имя или сущность, возможно, намеренно не используются. Это должно появляются не более одного раза в каждом списке атрибутов, и не должно присутствовать никакого атрибута-аргумента-предложения....

Example:

 [[maybe_unused]] void f([[maybe_unused]] bool thing1,
                        [[maybe_unused]] bool thing2) {
  [[maybe_unused]] bool b = thing1 && thing2;
    assert(b);
 }

Реализации не должны предупреждать, что b не используется, независимо от того, определен ли NDEBUG. - конец примера]

Для следующего примера:

int foo ( int bar) {
    bool unused_bool ;
    return 0;
}

и clang, и gcc генерируют диагностику, используя -Wall -Wextra для bar и unused_bool (смотрите в прямом эфире).

При добавлении [[Maybe_unused]] диагностика отключается:

int foo ([[maybe_unused]] int bar) {
    [[maybe_unused]] bool unused_bool ;
    return 0;
}

увидеть его в прямом эфире.

До С++ 17

В С++ 11 альтернативная форма макроса UNUSED может быть сформирована с использованием лямбда-выражения (через Ben Deane) с захватом неиспользованной переменной:

#define UNUSED(x) [&x]{}()

Непосредственный вызов лямбда-выражения следует оптимизировать, учитывая следующий пример:

int foo (int bar) {
    UNUSED(bar) ;
    return 0;
}

мы можем видеть в Godbolt, что вызов оптимизирован:

foo(int):
xorl    %eax, %eax
ret

Ответ 9

макро-менее и переносимый способ объявить один или несколько параметров как неиспользуемые:

template <typename... Args> inline void unused(Args&&...) {}

int main(int argc, char* argv[])
{
    unused(argc, argv);
    return 0;
}

Ответ 10

Использование препроцессорных директив чаще всего считается злом. В идеале вы хотите избежать их, как Pest. Помните, что компилятор понимает ваш код, это просто, что позволяет другим программистам понять ваш код намного сложнее. Несколько десятков таких случаев здесь и там очень трудно читать для себя позже или для других прямо сейчас.

Одним из способов может быть объединение ваших параметров в какой-то класс аргументов. Затем вы могли использовать только подмножество переменных (что эквивалентно назначению 0) или иметь разные специализации этого класса аргументов для каждой платформы. Однако это может не стоить того, вам нужно проанализировать, будет ли он соответствовать.

Если вы можете прочитать невозможные шаблоны, вы можете найти дополнительные советы в книге "Исключительный С++". Если люди, которые будут читать ваш код, могут получить свой набор навыков, чтобы охватить сумасшедшие вещи, которые преподаются в этой книге, тогда у вас будет красивый код, который также можно легко прочитать. Компилятор также хорошо знал бы, что вы делаете (вместо того, чтобы скрывать все путем предварительной обработки)

Ответ 11

Вначале предупреждение генерируется определением переменной в исходном файле, а не в файле заголовка. Заголовок может оставаться чистым и должен, поскольку вы можете использовать что-то вроде doxygen для создания API-документации.

Я предполагаю, что у вас есть совершенно другая реализация в исходных файлах. В этих случаях вы можете либо прокомментировать параметр нарушения, либо просто написать параметр.

Пример:

func(int a, int b)
{
    b;
    foo(a);
}

Это может показаться загадочным, поэтому определяется макрос, такой как UNUSED. Способ MFC:

#ifdef _DEBUG
#define UNUSED(x)
#else
#define UNUSED(x) x
#endif

Подобно этому вы видите предупреждение, все еще находящееся в отладочных сборках, может быть полезно.

Ответ 12

Не всегда ли всегда комментировать имена параметров? Если вы не можете сделать что-то вроде

#ifdef _MSC_VER
# define P_(n) n
#else
# define P_(n)
#endif

void ProcessOps::sendToExternalApp(
    QString sAppName, QString sImagePath,
    qreal P_(qrLeft), qreal P_(qrTop), qreal P_(qrWidth), qreal P_(qrHeight))

Это немного менее уродливо.

Ответ 13

Использование UNREFERENCED_PARAMETER(p) может работать. Я знаю, что он определен в WinNT.h для систем Windows и может быть легко определен для gcc (если он еще не имеет его).

UNREFERENCED PARAMETER(p) определяется как

#define UNREFERENCED_PARAMETER(P)          (P)

в WinNT.h.

Ответ 14

Использовать флаг компилятора, например. флаг для GCC: -Wno-unused-variable

Ответ 15

Вы можете использовать __unused, чтобы сообщить компилятору, что переменная не может использоваться.

- (void)myMethod:(__unused NSObject *)theObject    
{
    // there will be no warning about `theObject`, because you wrote `__unused`

    __unused int theInt = 0;
    // there will be no warning, but you are still able to use `theInt` in the future
}

Ответ 16

Это хорошо работает, но требует С++ 11

template <typename ...Args>
void unused(Args&& ...args)
{
  (void)(sizeof...(args));
}

Ответ 17

В С++ 11 это решение, которое я использую:

template<typename... Ts> inline void Unreferenced(Ts&&...) {}

int Foo(int bar) 
{
    Unreferenced(bar);
    return 0;
}

int Foo2(int bar1, int bar2) 
{
    Unreferenced(bar1, bar2);
    return 0;
}

Проверено на переносимость (по крайней мере, на современных msvc, clang и gcc) и не создает дополнительного кода при включенной оптимизации. Без оптимизации выполняется дополнительный вызов функции, и ссылки на параметры копируются в стек, но макросы не используются.

Если дополнительный код является проблемой, вы можете использовать это объявление:

(decltype(Unreferenced(bar1, bar2)))0;

но в этот момент макрос обеспечивает лучшую читаемость:

#define UNREFERENCED(...) { (decltype(Unreferenced(__VA_ARGS__)))0; }

Ответ 18

Я нашел, что большинство представленных ответов работают только для локальной неиспользуемой переменной и вызовет ошибку компиляции для неиспользуемой статической глобальной переменной.

Другой макрос, необходимый для подавления предупреждения о неиспользуемой статической глобальной переменной.

template <typename T>
const T* UNUSED_VARIABLE(const T& dummy) { 
    return &dummy;
}
#define UNUSED_GLOBAL_VARIABLE(x) namespace {\
    const auto dummy = UNUSED_VARIABLE(x);\
}

static int a = 0;
UNUSED_GLOBAL_VARIABLE(a);

int main ()
{
    int b = 3;
    UNUSED_VARIABLE(b);
    return 0;
}

Это работает, потому что для нестатической глобальной переменной в анонимном пространстве имен не сообщается никаких предупреждений.

Требуется С++ 11, хотя

 g++  -Wall -O3  -std=c++11 test.cpp

Ответ 19

Я видел это вместо способа (void)param2 заставить замолчать предупреждение:

void foo(int param1, int param2)
{
    std::ignore = param2;
    bar(param1);
}

Похоже, это было добавлено в С++ 11

Ответ 20

Я не вижу вашей проблемы с предупреждением. Документируйте его в заголовке метода/функции, чтобы компилятор xy выдавал (правильное) предупреждение здесь, но эти тезисы необходимы для платформы z.

Предупреждение правильное, нет необходимости отключать его. Это не делает недействительной программу, но она должна быть документирована, что есть причина.