Ist die Verwendung von #pragma warning push / pop der richtige Weg, um die Warnstufe vorübergehend zu ändern?

73

Hin und wieder ist es schwierig, C ++ - Code zu schreiben, der überhaupt keine Warnungen ausgibt. Es ist jedoch eine gute Idee, Warnungen zu aktivieren. Daher ist es häufig erforderlich, Warnungen für ein bestimmtes Konstrukt zu deaktivieren und in allen anderen Codeteilen zu aktivieren.

Ich habe bisher zwei Möglichkeiten gesehen, dies zu tun.

Der erste ist zu verwenden #pragma warning( push )und #pragma warning( pop ):

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

Die zweite ist zu verwenden #pragma warning( default ):

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

Das Problem, das ich in der zweiten Variante sehe, ist, dass die ursprüngliche Warnstufe verworfen wird - die Warnung war möglicherweise zuvor deaktiviert oder die Warnstufe wurde möglicherweise geändert. Die Verwendung defaultwürde diese Änderungen verwerfen.

Der erste Ansatz sieht sauber aus. Gibt es irgendwelche Probleme damit? Gibt es bessere Möglichkeiten, dies zu erreichen?

scharfer Zahn
quelle
Portabilität, aber da dies mit Visual-C ++ gekennzeichnet ist, ist dies wahrscheinlich kein Problem für Sie. Leider scheint es keine Lösung zu geben, die annähernd "asketisch ansprechend" ist. Ich gehe immer mit der Push / Pop-Methode.
Mark Storer

Antworten:

39

Die erste Methode ist der beste Weg, IMO. Ich kenne keine Probleme damit.

Denken Sie einfach daran, dass ein #pragma compilerspezifisch ist. Erwarten Sie also nicht, dass es auf jedem Compiler funktioniert :)

Goz
quelle
9
Ich hatte ein mögliches nerviges Problem beim ersten Ansatz. Wenn der \\code with ThatWarning hereHeader einen (Drittanbieter-) Header enthält und dieser Header einen enthält, #pragma warning( disable: AnotherWarning)deaktiviert der Pop die Deaktivierung. Während dies wohl eine gute Sache ist, tut der Bibliotheksdesigner möglicherweise etwas in einer Vorlage, die eine Warnung generiert, die er als sicher eingestuft hat. Jetzt wird bei jeder Verwendung dieser Vorlage in Ihrem Code diese Warnung generiert, sie wird jedoch als Bibliothek gekennzeichnet. Es ist überhaupt nicht klar, welche Zeile Ihres Codes eine Warnung in der Bibliothek auslöst.
Nach unten gerichteter Gott
3
@ DownwardFacingGod: Late-reply-o-rama .... aber ... das gleiche Problem würde auch mit der anderen Methode auftreten ...
Goz
1
Wie hier richtig angegeben, ist die erste Methode die beste und daran ist nichts auszusetzen. Dieser Punkt wurde in "C ++ Coding Standards 101 Regeln, Richtlinien und Best Practices" von Herb Sutter und Andrei Alexandrescu, 1. Auflage, 2005 (Seite 19) klar angegeben.
Amirfg
43

Dies funktioniert mit mehreren Compilern (und verschiedenen Versionen von Compilern).

Header "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

Header "Pop"

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

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

Eine Warnung

#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

Verwendung

// 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
// ...

Darüber hinaus können Include-Wachen überprüfen, ob es keine Pragmas für doppelte Push- / Pop- / Deaktivierungswarnungen gibt.

Aktualisieren


quelle
41

Für Sharptooth zu spät, aber für alle Googler da draußen:

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

ist die Abkürzung für (im Allgemeinen seit VS 2008 , aber in VS 2005 nur für Code Analyzer-Warnungen):

#pragma warning ( push )
#pragma warning ( disable: ThatWarning )
// one single line with ThatWarning
#pragma warning ( pop )
m3tikn0b
quelle
Danke vielmals! suppressist hier definitiv die richtige Antwort und viel eleganter als push/disable/popoder disable/enable.
Nicu Stiurca
war der einzige Weg in vs2012, Push-Deaktivierung etc .. funktionierte nicht
Michel Sanches
Ich vermute, dass dies die Methode ist, die die meisten Programmierer wollen.
David A. Gray
Noch ein Wort an die Weisen; das C-Präfix verlieren; benutze einfach die Nummer. Andernfalls generiert die # Pragma-Direktive noch mehr Warnungen und unternimmt nichts.
David A. Gray
1
Obwohl dies die eleganteste Methode ist (wenn man sagen kann, dass es so etwas gibt), funktioniert sie nicht immer wie beabsichtigt. Wie immer ist der Teufel im Detail: #pragma warning (suppress)funktioniert nur auf der nächsten Zeile von Code, nicht der nächste Block . Ich spreche das an, da TS "Code mit Warnung" angegeben hat.
Marcbf
13

Der richtige Ansatz (obwohl ein bisschen hässlich)

#ifdef _MSC_VER
 #pragma warning( push )
 #pragma warning( once: ThatWarning )
#endif
 //code with ThatWarning here
#ifdef _MSC_VER
 #pragma warning( pop )
#endif
Ronag
quelle
13
TS möchte eine Warnung für einen Teil des Codes vorübergehend deaktivieren. Die # Pragma-Warnung (einmal) funktioniert nicht, da die Warnung weiterhin angezeigt werden kann (nur einmal). Ich frage mich, ob die Aufsteiger die Lösung tatsächlich getestet haben. (Ich habe es getan, es hat nicht funktioniert).
Alex Che
'einmal' vs 'deaktivieren'. Ich glaube, unsere bescheidenen Leser werden es herausfinden. Stapelüberlaufleser gehören eindeutig zu den besten, die die Menschheit zu bieten hat. Oder so.
Mark Storer
3

Sie können bestimmte Warnungen in den Projekt- oder Dateioptionen deaktivieren. Diese Einstellung gilt als 'Standard' für diese # Pragmas im entsprechenden Bereich. Einige der Warnungen in VS2005 sind so nutzlos / ärgerlich, dass dies die Ausgabe bei Verwendung ziemlich aufräumt /W4.

Dies finden Sie unter Eigenschaften unter Konfigurationseigenschaften -> C / C ++ -> Erweitert.

Steve Townsend
quelle
2

Ich habe keine Probleme mit der ersten Variante. Möglicherweise ist es besser, Folgendes zu verwenden:

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

Dadurch werden Sie darauf hingewiesen, dass der Code immer noch Warnungen enthält, die Warnmeldungen jedoch nicht so störend sind. Aber das ist Geschmackssache.

Kirill V. Lyadvinsky
quelle
Diese Warnung: msdn.microsoft.com/en-us/library/1ywe7hcy(VS.80).aspx blutet ärgerlich, auch wenn Sie es nur einmal sehen;)
Goz
1
Das Problem hierbei ist, dass es nützlich sein kann, den Compiler dazu zu bringen, "Warnungen als Fehler zu behandeln". Für Fehler, die nicht behoben werden können (z. B. Abhängigkeiten von Drittanbietern), müssen Sie diese sicher deaktivieren.
Nach unten gerichteter Gott
0

Mit dem ersten Ansatz können Sie die spezifische Warneinstellung in einem lokalen Bereich ändern. Es speichert zuerst den gesamten aktuellen Warnstatus, indem es in den Stapel geschoben wird, wendet Ihre Warnänderungen an und stellt dann den letzten Warnstatus wieder her (Pop).

#pragma warning (push) #pragma warning (einmal: ThatWarning) // Code mit ThatWarning hier #pragma warning (pop)

Charlie
quelle