Contrassegno C ++ come obsoleto


147

Ho un metodo in un'interfaccia che voglio deprecare con C ++ portatile. Quando ho cercato su Google per tutto ciò che ho ottenuto è stata una soluzione specifica di Microsoft; #pragma deprecato e __declspec (deprecato) .

Una soluzione secondo premio sarebbe ifdef una soluzione MSVC e una GCC.
Grazie

Risposte:


193

In C ++ 14, è possibile contrassegnare una funzione come obsoleta utilizzando l' [[deprecated]]attributo (vedere la sezione 7.6.5 [dcl.attr.deprecated]).

Il token di attributo deprecated può essere utilizzato per contrassegnare nomi ed entità il cui uso è ancora consentito, ma è sconsigliato per qualche motivo.

Ad esempio, la seguente funzione fooè obsoleta:

[[deprecated]]
void foo(int);

È possibile fornire un messaggio che descriva perché il nome o l'entità sono stati deprecati:

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

Il messaggio deve essere una stringa letterale.

Per ulteriori dettagli, vedere "Contrassegno come obsoleto in C ++ 14" .


Puoi usare [[deprecato]] in una macro?
Daniel Ryan,

2
@Zammbi Dovresti essere in grado di farlo, poiché la macro viene gestita dal preprocessore prima della compilazione. Dovrebbe apparire [[obsoleto]] (e lasciare che gli avvisi relativi all'output del compilatore) vengano valutati.
Florian Castellane,

129

Questo dovrebbe fare il trucco:

#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);

Tuttavia, si verificheranno problemi se un tipo restituito da una funzione ha una virgola nel suo nome, ad es. std::pair<int, int>Poiché questo sarà interpretato dal preprocesor come passare 2 argomenti alla macro DEPRECATED. In tal caso dovresti digitare il tipo restituito.

Modifica: versione più semplice (ma forse meno ampiamente compatibile) qui .


6
Invece di #error, sarebbe meglio #define DEPRECATED (func) func
CesarB

1
mxp: la deprecazione è solo un avvertimento, quindi direi che un avvertimento che non è supportato è tutto ciò di cui hai bisogno.
Leon Timmermans

1
Sì, preferirei "#warning Devi implementare DEPRECATED per questo compilatore", o qualcosa del genere. Se ciò è impossibile, il facchino può #define FUNZIONE DEPRECATA (FUNC) e vivere senza di essa.
Steve Jessop

2
Sfortunatamente non esiste un modo standard per generare un avviso di compilazione in C ++: il messaggio P #pragma dovrà fare.
Michael Platings,

3
La sintassi dell'attributo di gcc consente che l'attributo si trovi negli stessi posti di __declspec(deprecated)adesso, quindi la macro può essere semplificata.
bames53,

57

Ecco una versione semplificata della mia risposta del 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);

Guarda anche:


17
Come fai le [[deprecate]]tue macro deprecate? :-)
graham.reeds

3
Non riesco a vedere alcuna differenza significativa tra queste due risposte. Perché l'hai pubblicato una seconda volta?
Tomáš Zato - Ripristina Monica il

4
Non è necessario avvolgerlo attorno alla funzione, quindi è DEPRECATED void foo(...);invece diDEPRECATED(void foo(...));
pastore

12
Avresti dovuto modificare la tua risposta del 2008 anziché pubblicarne una nuova.
Yakov Galka,

4
Potrebbe non essere così compatibile come l'altra mia risposta, quindi l'ho aggiunto separatamente.
Michael Platings,

22

In GCC puoi dichiarare la tua funzione con l'attributo deprecato in questo modo:

void myfunc() __attribute__ ((deprecated));

Ciò attiverà un avviso in fase di compilazione quando tale funzione viene utilizzata in un file .c.

Ulteriori informazioni sono disponibili in "Pragmi diagnostici" all'indirizzo http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html


8

Ecco una risposta più completa per il 2018.

In questi giorni, molti strumenti ti consentono non solo di contrassegnare qualcosa come deprecato, ma anche di fornire un messaggio. Questo ti permette di dire alle persone quando qualcosa è stato deprecato e forse di indirizzarle verso un sostituto.

C'è ancora molta varietà nel supporto del compilatore:

  • C ++ 14 supporta [[deprecated]]/ [[deprecated(message)]].
  • __attribute__((deprecated)) è supportato da GCC 4.0+ e ARM 4.1+
  • __attribute__((deprecated))ed __attribute__((deprecated(message)))è supportato per:
    • GCC 4.5+
    • Diversi compilatori che si mascherano come GCC 4.5+ (impostando __GNUC__/ __GNUC_MINOR__/__GNUC_PATCHLEVEL__ )
    • Compilatore Intel C / C ++ che risale almeno al 16 (non ci si può fidare __GNUC__/ __GNUC_MINOR__, lo hanno semplicemente impostato su qualsiasi versione di GCC installata)
    • ARM 5.6+
  • MSVC supporta __declspec(deprecated)dal 13.10 (Visual Studio 2003)
  • MSVC supporta __declspec(deprecated(message))dalla 14.0 (Visual Studio 2005)

È inoltre possibile utilizzare [[gnu::deprecated]]in versioni recenti di clang in C ++ 11, basato su __has_cpp_attribute(gnu::deprecated).

Ho alcune macro in Hedley per gestire tutto questo automaticamente, che tengo aggiornato, ma la versione corrente (v2) è simile a questa:

#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

Lascerò come un esercizio per capire come sbarazzarsi di macro *_VERSION_CHECKe *_HAS_ATTRIBUTEse non si desidera utilizzare Hedley (ho scritto Hedley in gran parte, quindi non dovrei pensarci su base regolare).

Se si utilizza GLib, è possibile utilizzare le macro G_DEPRECATEDe G_DEPRECATED_FOR. Non sono robusti come quelli di Hedley, ma se usi già GLib non c'è nulla da aggiungere.


4

Trattare con progetti portatili è quasi inevitabile che ad un certo punto sia necessaria una sezione di alternative preelaborate per una vasta gamma di piattaforme. #ifdef questo #ifdef quello e così via.

In una tale sezione potresti benissimo definire in modo condizionale un modo per deprecare i simboli. La mia preferenza è di solito definire una macro di "avviso" poiché la maggior parte delle toolchain supporta gli avvisi del compilatore personalizzati. Quindi è possibile continuare con una specifica macro di avviso per l'ammortamento, ecc. Per le piattaforme che supportano metodi di ammortamento dedicati, è possibile utilizzare quello invece degli avvisi.


1

Per Intel Compiler v19.0, utilizzare questo come __INTEL_COMPILERvaluta per 1900:

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

Funziona con i seguenti livelli di lingua:

  • Supporto C ++ 17 (/ Qstd = c ++ 17)
  • Supporto C ++ 14 (/ Qstd = c ++ 14)
  • Supporto C ++ 11 (/ Qstd = c ++ 11)
  • Supporto C11 (/ Qstd = c11)
  • Supporto C99 (/ Qstd = c99)

Il compilatore Intel ha ciò che sembra un bug in quanto non supporta l' [[deprecated]]attributo su determinati elementi del linguaggio che fanno tutti gli altri compilatori. Ad esempio, compilare la v6.0.0 della libreria (straordinariamente eccezionale) {fmtlib / fmt} su GitHub con Intel Compiler v19.0. Si romperà. Quindi vedere la correzione nel commit GitHub .


Questo non è corretto; Gli attributi C ++ non funzionano in modalità C su ICC. Esempio . __attribute__((deprecated)), OTOH, funziona in C e C ++ risalendo almeno a ICC 13.0, probabilmente molto più lontano (Intel tende a non documentare questo tipo di cose, quindi non posso esserne sicuro).
nemequ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.