Да, но вы, скорее всего, получите еще одно предупреждение.
Стандартный способ сделать это: (void)iid;
.
С технической точки зрения это все равно могло бы загрузить iid
в регистр и ничего не сделать. Конечно, это очень глупо со стороны компилятора (я сомневаюсь, что кто-либо когда-либо сделает это, если он удалит компилятор), но это более серьезная проблема, если игнорируемое выражение относится к наблюдаемому поведению, например вызовы функций ввода-вывода или чтение и запись volatile
переменных.
Возникает интересный вопрос: можем ли мы взять выражение и полностью его игнорировать?
То есть то, что мы имеем сейчас, это:
#define USE(x) (void)(x)
// use iid in an expression to get rid of warning, but have no observable effect
USE(iid);
// hm, result of expression is gone but expression is still evaluated
USE(std::cout << "hmmm" << std::endl);
Это близко к решению:
// sizeof doesn't evaluate the expression
#define USE(x) (void)(sizeof(x))
Но терпит неудачу с:
void foo();
// oops, cannot take sizeof void
USE(foo());
Решение состоит в том, чтобы просто:
// use expression as sub-expression,
// then make type of full expression int, discard result
#define USE(x) (void)(sizeof((x), 0))
Что гарантирует отсутствие операции. забастовка>
Редактировать: Вышеупомянутое действительно не гарантировало никакого эффекта, но я опубликовал без тестирования. При тестировании он снова генерирует предупреждение, по крайней мере, в MSVC 2010, поскольку значение не используется. Это нехорошо, время для новых трюков!
Напоминание: мы хотим «использовать» выражение без его вычисления. Как это может быть сделано? Нравится:
#define USE(x) ((void)(true ? 0 : (x)))
У этого есть простая проблема, как и в прошлый раз (на самом деле хуже), в том, что (x)
нужно конвертировать в int
. Это, опять же, тривиально исправить:
#define USE(x) ((void)(true ? 0 : ((x), 0)))
И мы вернулись к тому же эффекту, что и в прошлый раз (никакого), но на этот раз x
"используется", поэтому мы не получаем никаких предупреждений. Готово, верно?
На самом деле есть еще одна проблема с этим решением (и она присутствовала и в последнем не-решении, но осталась незамеченной), и она возникает в этом примере:
struct foo {};
void operator,(const foo&, int) {}
foo f;
USE(f); // oops, void isn't convertible to int!
То есть, если тип выражения (x)
перегружает оператор запятой чем-то, что не может быть преобразовано в int
, решение терпит неудачу. Конечно, маловероятно, но ради полного перебора мы можем исправить это с помощью:
#define USE(x) ((void)(true ? 0 : ((x), void(), 0)))
Чтобы убедиться, что мы действительно получаем ноль. Этот трюк предложил вам Йоханнес.
Также, как уже отмечалось, если вышесказанного недостаточно, достаточно глупый компилятор потенциально может «загрузить» выражение 0
(в регистр или что-то еще), а затем проигнорировать его.
Я думаю, что избавиться от этого невозможно, так как нам в конечном итоге нужно выражение, чтобы получить какой-то тип, который нужно игнорировать, но если я когда-нибудь подумаю об этом, я добавлю его.
person
GManNickG
schedule
27.10.2010
#define variableName exit(-1)
- person Benoit   schedule 27.10.2010