C ++ als veraltet markieren

147

Ich habe eine Methode in einer Schnittstelle, die ich mit portablem C ++ verwerfen möchte. Als ich danach googelte, bekam ich nur eine Microsoft-spezifische Lösung. #pragma veraltet und __declspec (veraltet) .

Eine Lösung mit dem zweiten Preis wäre, eine MSVC- und eine GCC-Lösung zu definieren.
Vielen Dank

Diederik
quelle

Antworten:

193

In C ++ 14 können Sie eine Funktion mithilfe des [[deprecated]]Attributs als veraltet markieren (siehe Abschnitt 7.6.5 [dcl.attr.deprecated]).

Das Attribut-Token deprecated kann verwendet werden, um Namen und Entitäten zu markieren, deren Verwendung noch zulässig ist, aus irgendeinem Grund jedoch nicht empfohlen wird.

Die folgende Funktion fooist beispielsweise veraltet:

[[deprecated]]
void foo(int);

Es ist möglich, eine Nachricht bereitzustellen, die beschreibt, warum der Name oder die Entität veraltet war:

[[deprecated("Replaced by bar, which has an improved interface")]]
void foo(int);

Die Nachricht muss ein String-Literal sein.

Weitere Informationen finden Sie unter „In C ++ 14 als veraltet markieren“ .

Joseph Mansfield
quelle
Können Sie [[veraltet]] in einem Makro verwenden?
Daniel Ryan
2
@Zammbi Dies sollte möglich sein, da das Makro vor der Kompilierung vom Präprozessor verarbeitet wird. [[veraltet]] sollte dort erscheinen (und den Compiler entsprechende Warnungen ausgeben lassen), wo das Makro ausgewertet wird.
Florian Castellane
129

Dies sollte den Trick tun:

#ifdef __GNUC__
#define DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED(func) __declspec(deprecated) func
#else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED(func) func
#endif

...

//don't use me any more
DEPRECATED(void OldFunc(int a, float b));

//use me instead
void NewFunc(int a, double b);

Es treten jedoch Probleme auf, wenn ein Funktionsrückgabetyp ein Komma im Namen hat, z. B. std::pair<int, int>da dies vom Präprozessor so interpretiert wird, dass 2 Argumente an das Makro DEPRECATED übergeben werden. In diesem Fall müssten Sie den Rückgabetyp eingeben.

Bearbeiten: einfachere (aber möglicherweise weniger weitgehend kompatible) Version hier .

Michael Platings
quelle
6
Anstelle von #error ist es besser, # DEPRECATED (func)
func
1
mxp: Die Ablehnung ist nur eine Warnung, und daher würde ich sagen, dass eine Warnung, dass sie nicht unterstützt wird, alles ist, was Sie brauchen.
Leon Timmermans
1
Ja, ich würde mich für "#warning Sie müssen DEPRECATED für diesen Compiler implementieren" oder ähnliches entscheiden. Wenn dies nicht möglich ist, kann der Portier DEPRECATED (FUNC) FUNC definieren und ohne ihn leben.
Steve Jessop
2
Leider gibt es keine Standardmethode zum Ausgeben einer Kompilierungswarnung in C ++: Die P # Pragma-Nachricht muss ausreichen.
Michael Platings
3
Die Attributsyntax von gcc ermöglicht, dass sich das Attribut an denselben Stellen wie __declspec(deprecated)jetzt befindet, sodass das Makro vereinfacht werden kann.
Bames53
57

Hier ist eine vereinfachte Version meiner Antwort von 2008 :

#if defined(__GNUC__) || defined(__clang__)
#define DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED __declspec(deprecated)
#else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED
#endif

//...

//don't use me any more
DEPRECATED void OldFunc(int a, float b);

//use me instead
void NewFunc(int a, double b);

Siehe auch:

Michael Platings
quelle
17
Wie machen Sie [[deprecate]]Ihre veralteten Makros? :-)
graham.reeds
3
Ich kann keinen signifikanten Unterschied zwischen diesen beiden Antworten feststellen. Warum hast du es ein zweites Mal gepostet?
Tomáš Zato - Wiedereinsetzung Monica
4
Sie müssen es nicht um die Funktion wickeln, also ist es DEPRECATED void foo(...);stattDEPRECATED(void foo(...));
dshepherd
12
Sie sollten Ihre Antwort für 2008 bearbeitet haben, anstatt eine neue zu veröffentlichen.
Yakov Galka
4
Dies ist möglicherweise nicht so weitgehend kompatibel wie meine andere Antwort, daher habe ich dies separat hinzugefügt.
Michael Platings
22

In GCC können Sie Ihre Funktion mit dem folgenden Attribut deklarieren:

void myfunc() __attribute__ ((deprecated));

Dies löst eine Warnung zur Kompilierungszeit aus, wenn diese Funktion in einer .c-Datei verwendet wird.

Weitere Informationen finden Sie unter "Diagnostic Pragmas" unter http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html

Terje Mikal
quelle
8

Hier ist eine vollständigere Antwort für 2018.

Heutzutage können Sie mit vielen Tools nicht nur etwas als veraltet markieren, sondern auch eine Nachricht bereitstellen. Auf diese Weise können Sie Personen mitteilen, wenn etwas veraltet ist, und sie möglicherweise auf einen Ersatz hinweisen.

Die Compiler-Unterstützung ist immer noch sehr vielfältig:

  • C ++ 14 unterstützt [[deprecated]]/ [[deprecated(message)]].
  • __attribute__((deprecated)) wird von GCC 4.0+ und ARM 4.1+ unterstützt
  • __attribute__((deprecated))und __attribute__((deprecated(message)))wird unterstützt für:
    • GCC 4.5+
    • Mehrere Compiler, die sich als GCC 4.5+ tarnen (durch Setzen von __GNUC__/ __GNUC_MINOR__/__GNUC_PATCHLEVEL__ )
    • Intel C / C ++ Compiler geht auf mindestens 16 zurück (Sie können nicht vertrauen __GNUC__/ __GNUC_MINOR__, sie setzen es einfach auf die Version von GCC, die installiert ist)
    • ARM 5.6+
  • MSVC unterstützt __declspec(deprecated)seit 13.10 (Visual Studio 2003)
  • MSVC unterstützt __declspec(deprecated(message))seit 14.0 (Visual Studio 2005)

Sie können auch [[gnu::deprecated]]in neueren Versionen von clang in C ++ 11 verwenden, basierend auf __has_cpp_attribute(gnu::deprecated).

Ich habe einige Makros in Hedley , um all dies automatisch zu erledigen, die ich auf dem neuesten Stand halte, aber die aktuelle Version (v2) sieht folgendermaßen aus:

#if defined(__cplusplus) && (__cplusplus >= 201402L)
#  define HEDLEY_DEPRECATED(since) [[deprecated("Since " #since)]]
#  define HEDLEY_DEPRECATED_FOR(since, replacement) [[deprecated("Since " #since "; use " #replacement)]]
#elif \
  HEDLEY_GCC_HAS_EXTENSION(attribute_deprecated_with_message,4,5,0) || \
  HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
  HEDLEY_ARM_VERSION_CHECK(5,6,0)
#  define HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
#  define HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
#elif \
  HEDLEY_GCC_HAS_ATTRIBUTE(deprcated,4,0,0) || \
  HEDLEY_ARM_VERSION_CHECK(4,1,0)
#  define HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
#  define HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
#elif HEDLEY_MSVC_VERSION_CHECK(14,0,0)
#  define HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
#  define HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
#elif HEDLEY_MSVC_VERSION_CHECK(13,10,0)
#  define HEDLEY_DEPRECATED(since) _declspec(deprecated)
#  define HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
#else
#  define HEDLEY_DEPRECATED(since)
#  define HEDLEY_DEPRECATED_FOR(since, replacement)
#endif

Ich lasse es als Übung, um herauszufinden, wie man das *_VERSION_CHECKund loswird*_HAS_ATTRIBUTE Makros wenn man Hedley nicht verwenden möchte (ich habe Hedley größtenteils geschrieben, damit ich nicht regelmäßig darüber nachdenken muss).

Wenn Sie GLib verwenden, können Sie die Makros G_DEPRECATEDund verwenden G_DEPRECATED_FOR. Sie sind nicht so robust wie die von Hedley, aber wenn Sie bereits GLib verwenden, gibt es nichts hinzuzufügen.

nemequ
quelle
4

Bei tragbaren Projekten ist es fast unvermeidlich, dass Sie irgendwann einen Abschnitt vorverarbeiteter Alternativen für eine Reihe von Plattformen benötigen. #ifdef this #ifdef that und so weiter.

In einem solchen Abschnitt können Sie sehr gut eine Möglichkeit definieren, Symbole zu verwerfen. Normalerweise definiere ich lieber ein "Warn" -Makro, da die meisten Toolchains benutzerdefinierte Compiler-Warnungen unterstützen. Anschließend können Sie mit einem bestimmten Warnmakro für Verfall usw. fortfahren. Für Plattformen, die dedizierte Verfallsmethoden unterstützen, können Sie dieses anstelle von Warnungen verwenden.

Sharkin
quelle
1

Verwenden Sie dies für Intel Compiler v19.0 als __INTEL_COMPILERAuswertung für 1900:

#  if defined(__INTEL_COMPILER)
#    define DEPRECATED [[deprecated]]
#  endif

Funktioniert für die folgenden Sprachniveaus:

  • C ++ 17-Unterstützung (/ Qstd = c ++ 17)
  • C ++ 14-Unterstützung (/ Qstd = c ++ 14)
  • C ++ 11-Unterstützung (/ Qstd = c ++ 11)
  • C11-Unterstützung (/ Qstd = c11)
  • C99-Unterstützung (/ Qstd = c99)

Der Intel Compiler hat den Anschein, dass er das [[deprecated]]Attribut für bestimmte Sprachelemente, das alle anderen Compiler ausführen, nicht unterstützt . Kompilieren Sie beispielsweise v6.0.0 der (bemerkenswert hervorragenden) {fmtlib / fmt} -Bibliothek auf GitHub mit Intel Compiler v19.0. Es wird brechen. Dann sehen Sie sich das Update im GitHub-Commit an .

Contango
quelle
Das ist falsch; C ++ - Attribute funktionieren im C-Modus auf ICC nicht. Beispiel . __attribute__((deprecated)), OTOH, funktioniert in C und C ++ und geht auf mindestens ICC 13.0 zurück, wahrscheinlich viel weiter (Intel neigt dazu, solche Dinge nicht zu dokumentieren, daher kann ich nicht sicher sein).
Nemequ