Правильно ли использовать #pragma warning push / pop для временного изменения уровня предупреждения?

Иногда бывает сложно написать код на C ++, который бы вообще не выдавал предупреждений. Однако включение предупреждений - хорошая идея. Поэтому часто бывает необходимо отключить предупреждения вокруг какой-то конкретной конструкции и включить их во всех других частях кода.

До сих пор я видел два способа сделать это.

Первый - использовать #pragma warning( push ) и #pragma warning( pop ):

 #pragma warning( push )
 #pragma warning( disable: ThatWarning )
 //code with ThatWarning here
 #pragma warning( pop )

Второй - использовать #pragma warning( default ):

 #pragma warning( disable: ThatWarning )
 //code with ThatWarning here
 #pragma warning( default: ThatWarning )

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

Первый подход выглядит чистым. Есть ли с этим проблемы? Есть ли лучшие способы добиться того же?


person sharptooth    schedule 16.11.2010    source источник
comment
Переносимость, но поскольку это помечено как visual-c ++, это, вероятно, не проблема для вас. К сожалению, не существует решения, которое было бы хоть сколько-нибудь аскетически приятным. Я всегда использую метод push / pop.   -  person Mark Storer    schedule 22.04.2019


Ответы (7)


Первый способ - лучший способ сделать это, ИМО. Я не знаю никаких проблем с этим.

Просто имейте в виду, что #pragma зависит от компилятора, поэтому не ожидайте, что он будет работать с каждым компилятором :)

person Goz    schedule 16.11.2010
comment
При первом подходе я столкнулся с возможной неприятной проблемой. Если в \\code with ThatWarning here есть (сторонний) заголовок, а в этом заголовке есть #pragma warning( disable: AnotherWarning), то всплывающее окно отключает отключение. Хотя, возможно, это и хорошо, разработчик библиотеки может что-то делать в шаблоне, который генерирует предупреждение, которое они определили как безопасное. Теперь любое использование этого шаблона в вашем коде вызовет это предупреждение, но оно будет помечено как библиотека. Совершенно непонятно, какая строка вашего кода вызывает предупреждение в библиотеке. - person Downward Facing God; 08.08.2011
comment
@DownwardFacingGod: Late-reply-o-rama .... но ... та же проблема может возникнуть и с другим методом ... - person Goz; 13.03.2016
comment
Как здесь правильно сказано, первый метод является лучшим, и в этом нет ничего плохого. Этот момент четко сформулирован в «Стандартах программирования C ++ 101 Правила, рекомендации и передовые методы» Херба Саттера и Андрея Александреску, 1-е издание, 2005 г. (стр. 19). - person amirfg; 17.07.2019

Это будет работать с несколькими компиляторами (и разными версиями компиляторов).

Заголовок "push"

#if defined(__clang__)
# pragma clang diagnostic push
#endif

#if defined(_MSC_VER)
# pragma warning(push)
#endif

#if defined(YOUR_FAVORITE_COMPILER)
# pragma your compiler push warning
#endif

Заголовок "поп"

#if defined(__clang__)
# pragma clang diagnostic pop
#endif

#if defined(_MSC_VER)
# pragma warning(pop)
#endif

Некоторое предупреждение

#if defined(__clang__)
# pragma clang diagnostic ignored "-Wunused-parameter"
# pragma clang diagnostic ignored "-Wunused-variable"
#  if __has_warning("-Wnew-special-warning")
#   pragma clang diagnostic ignored "-Wnew-special-warning"
#  endif
#endif

#if defined(_MSC_VER)
# pragma warning(disable: 4100) // unreferenced formal parameter
# if _MSC_VER > _MSC_SOME_VERSION
#  pragma warning(disable: xxxx) // disable one more for special version
# endif
#endif

использование

// This code reports warnings
// ...
#include <ignore_compiler_warning/push>
#include <ignore_compiler_warning/warning_type_1>
#include <ignore_compiler_warning/warning_type_2>
#include <ignore_compiler_warning/warning_type_3>
// This code ignores warnings type_{1,2,3}
// ...
#include <ignore_compiler_warning/pop>
// Back to reporting warnings
// ...

Дополнительно включаемые охранники могут проверять отсутствие прагм двойного push / pop / disable-warning.

Обновлять

person Community    schedule 27.08.2013

Слишком поздно для острого зуба, но для всех гуглеров:

#pragma warning ( suppress: ThatWarning )
// one single line with ThatWarning

сокращенно от (обычно начиная с VS 2008, но в VS 2005 только для предупреждений анализатора кода):

#pragma warning ( push )
#pragma warning ( disable: ThatWarning )
// one single line with ThatWarning
#pragma warning ( pop )
person m3tikn0b    schedule 27.08.2013
comment
Большое спасибо! suppress определенно правильный ответ здесь, и он намного элегантнее, чем push/disable/pop или disable/enable. - person Nicu Stiurca; 19.02.2016
comment
был единственный рабочий способ в vs2012, push disable и т. д. не сработал - person Michel Sanches; 18.08.2016
comment
Я подозреваю, что это тот метод, который нужен большинству программистов. - person David A. Gray; 03.08.2018
comment
Еще одно слово мудрым; потерять префикс C; просто используйте номер. В противном случае директива #pragma генерирует еще больше предупреждений и ничего не делает. - person David A. Gray; 03.08.2018
comment
Хотя это самый элегантный метод (если можно так сказать), он не всегда работает так, как задумано. Как всегда, дьявол кроется в деталях: #pragma warning (suppress) работает только со следующей строкой кода, а не со следующим блоком. Я поднимаю этот вопрос, поскольку TS заявила код с предупреждением. - person marcbf; 16.07.2019

Правильный подход (хотя и немного некрасивый)

#ifdef _MSC_VER
 #pragma warning( push )
 #pragma warning( once: ThatWarning )
#endif
 //code with ThatWarning here
#ifdef _MSC_VER
 #pragma warning( pop )
#endif
person ronag    schedule 16.11.2010
comment
TS хочет временно отключить предупреждение для некоторой части кода. #pragma warning (once) не сработает, так как он по-прежнему позволяет отображать предупреждение (только один раз). Интересно, действительно ли сторонники протестировали решение. (Я сделал, не сработало). - person Alex Che; 22.12.2014
comment
«один раз» против «отключить». Я верю, что наши скромные читатели поймут это. Читатели Stack overflow явно являются одними из лучших, что может предложить человечество. Или что-то. - person Mark Storer; 22.04.2019

Вы можете отключить определенные предупреждения в параметрах проекта или файла, и этот параметр применяется как «по умолчанию» для этих #pragmas в соответствующей области. Некоторые предупреждения в VS2005 настолько бесполезны / раздражают, что это немного очищает вывод, если используется /W4.

Это находится в разделе «Свойства» в разделе «Свойства конфигурации» -> «C / C ++» -> «Дополнительно».

person Steve Townsend    schedule 16.11.2010

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

 #pragma warning( push )
 #pragma warning( once: ThatWarning )
 //code with ThatWarning here
 #pragma warning( pop )

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

person Kirill V. Lyadvinsky    schedule 16.11.2010
comment
Это предупреждение: msdn.microsoft.com/en-us/ library / 1ywe7hcy (VS.80) .aspx раздражает кровью, даже если вы видите это только один раз;) - person Goz; 16.11.2010
comment
Проблема здесь в том, что может быть полезно заставить компилятор обрабатывать предупреждения как ошибки. Для ошибок, которые не могут быть исправлены (например, некоторых сторонних зависимостей), вам необходимо безопасно отключить. - person Downward Facing God; 08.08.2011

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

#pragma warning (push) #pragma warning (once: ThatWarning) // здесь код с ThatWarning #pragma warning (pop)

person Charlie    schedule 23.04.2020