2008-11-17 4 views

Répondre

129

En C++ 14, vous pouvez marquer une fonction comme obsolète à l'aide de l'attribut [[deprecated]] (voir la section 7.6.5 [dcl.attr.deprecated]).

L'attribut-jeton deprecated peut être utilisé pour marquer les noms et les entités dont l'utilisation est encore autorisée, mais elle est découragée pour une raison quelconque.

Par exemple, la fonction suivante foo est dépréciée:

[[deprecated]] 
void foo(int); 

Il est possible de fournir un message qui décrit pourquoi le nom ou l'entité a été dépréciés:

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

Le message doit être un littéral de chaîne.

Pour plus de détails, voir “Marking as deprecated in C++14”.

+0

Pouvez-vous utiliser [[déprécié]] dans une macro? – Zammbi

+1

@Zammbi Vous devriez pouvoir, car la macro est traitée par le préprocesseur avant la compilation. [[obsolète]] devrait apparaître (et laisser les avertissements liés à la sortie du compilateur) où la macro est évaluée. –

21

Dans GCC, vous pouvez déclarer votre fonction avec l'attribut dépréciée comme ceci:

void myfunc() __attribute__ ((deprecated)); 

Cela déclenchera un avertissement de compilation lorsque cette fonction est utilisée dans un fichier .c.

Vous pouvez trouver plus d'informations sous la rubrique « pragma diagnostic » à http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html

4

Faire face à des projets portables, il est presque inévitable que vous avez besoin à un moment donné une partie des alternatives prétraités pour une gamme de plates-formes. #ifdef ce #ifdef cela et ainsi de suite.

Dans une telle section, vous pourriez très bien définir un moyen de déprécier les symboles. Ma préférence est généralement de définir une macro "warning" puisque la plupart des toolchains supportent les warnings du compilateur. Ensuite, vous pouvez continuer avec une macro d'avertissement spécifique pour la dépréciation, etc. Pour les plates-formes qui prennent en charge les méthodes de dépréciation dédiées, vous pouvez l'utiliser à la place des avertissements.

116

Cela devrait faire l'affaire:

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

Cependant, vous rencontrerez des problèmes si un type de retour de la fonction a une virgule dans son nom par exemple std::pair<int, int> car cela sera interprété par le préprocesseur comme passant 2 arguments à la macro DEPRECATED. Dans ce cas, vous devrez typedef le type de retour.

Éditer: version plus simple (mais peut-être moins largement compatible) here.

+5

Au lieu de #error, il vaudrait mieux #define DEPRECATED (func) func – CesarB

+0

@CesarB: Je ne suis pas d'accord; S'il n'y avait pas d'erreur, il n'y aurait aucun moyen de remarquer que quelque chose d'inattendu est arrivé. – foraidt

+1

mxp: La dépréciation est seulement un avertissement, et donc je dirais qu'un avertissement qu'il n'est pas supporté est tout ce dont vous avez besoin. –

39

est ici une version simplifiée de mon 2008 answer:

#ifdef __GNUC__ 
#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); 
+10

Comment '[[déprécier]]' vos macros dépréciées? :-) –

+1

Je ne vois pas de différence significative entre ces deux réponses. Pourquoi l'avez-vous posté une deuxième fois? –

+3

Vous ne devez pas l'enrouler autour de la fonction donc c'est 'DEPRECATED void foo (...);' au lieu de 'DEPRECATED (void foo (...));' – dshepherd

2

Voici une réponse plus complète pour 2018.

Ces jours-ci, beaucoup d'outils vous permettent de ne pas marquer quelque chose comme dépréciée, mais également fournir un message. Cela vous permet de dire aux gens quand quelque chose a été déprécié, et peut-être les diriger vers un remplacement.

Il y a encore beaucoup de variété dans le soutien du compilateur:

  • 14 C++ prend en charge [[deprecated]]/[[deprecated(message)]].
  • __attribute__((deprecated)) est supporté par GCC 4.0+ et ARM 4.1+
  • __attribute__((deprecated)) et __attribute__((deprecated(message))) est supporté pour:
    • GCC 4.5+
    • Plusieurs compilateurs qui font passer pour GCC 4.5+ (en définissant __GNUC__/__GNUC_MINOR__ /)
    • Compilateur Intel C/C++ remontant à au moins 16 (vous ne pouvez pas faire confiance __GNUC__/__GNUC_MINOR__, ils le définissent simplement à la version de GCC est installée)
    • ARM 5.6+
  • MSVC soutient __declspec(deprecated) depuis 13.10 (Visual Studio 2003)
  • MSVC prend en charge __declspec(deprecated(message)) depuis 14.0 (Visual Studio 2005)

Vous pouvez également utiliser [[gnu::deprecated]] dans les versions récentes de clang en C++ 11, basé sur __has_cpp_attribute(gnu::deprecated).

J'ai quelques macros dans Hedley pour gérer tout cela automatiquement que je garde jusqu'à ce jour, mais la version actuelle (v2) ressemble à ceci:

#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 

Je vais laisser comme un exercice à comprendre comment se débarrasser des macros *_VERSION_CHECK et *_HAS_ATTRIBUTE si vous ne voulez pas utiliser Hedley (j'ai écrit Hedley en grande partie pour ne pas avoir à y penser régulièrement). Si vous utilisez GLib, vous pouvez utiliser les macros G_DEPRECATED et G_DEPRECATED_FOR. Ils ne sont pas aussi robustes que ceux de Hedley, mais si vous utilisez déjà GLib il n'y a rien à ajouter.