2008-11-17 16 views

Respuesta

129

En C++ 14, puede marcar una función como obsoleta utilizando el atributo [[deprecated]] (consulte la sección 7.6.5 [dcl.attr.deprecated]).

El atributo tokendeprecated se puede utilizar para marcar los nombres y entidades cuyo uso todavía está permitido, pero se desanima por alguna razón.

Por ejemplo, la función foo siguiente es obsoleto:

[[deprecated]] 
void foo(int); 

Es posible proporcionar un mensaje que describa por qué el nombre o entidad está desfasado:

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

el mensaje debe ser una cadena literal.

Para obtener más información, consulte “Marking as deprecated in C++14”.

+0

¿Se puede usar [[obsoleto]] en una macro? – Zammbi

+1

@Zammbi Debería poder hacerlo, ya que la macro es manejada por el preprocesador antes de la compilación. [[deprecated]] debería aparecer (y dejar que el compilador muestre advertencias relacionadas) donde se evalúa la macro. –

21

En GCC puede declarar su función con el atributo obsoleto como esto:

void myfunc() __attribute__ ((deprecated)); 

Esto activará una advertencia de tiempo de compilación cuando esa función se utiliza en un archivo .c.

Puede encontrar más información en "pragmas de diagnóstico" en http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html

4

se trata de proyectos portátiles Es casi inevitable que en algún momento necesita una sección de alternativas que se procesan para una variedad de plataformas. #ifdef this #ifdef eso y así sucesivamente.

En una sección de este tipo, podría definir condicionalmente una forma de desaprobar símbolos. Mi preferencia suele ser definir una macro de "advertencia" ya que la mayoría de las cadenas de herramientas admiten advertencias de compilación personalizadas. Luego puede continuar con una macro de advertencia específica para obsoletos, etc. Para las plataformas que admiten métodos de obsolescencia dedicados, puede usar eso en lugar de advertencias.

116

Esto debería hacer el truco:

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

Sin embargo, se encontrará con problemas si un tipo de retorno de la función tiene una comas en su nombre, por ejemplo, std::pair<int, int> ya que esto será interpretado por el preprocesador como pasar 2 argumentos a la macro DEPRECATED. En ese caso, tendrías que escribir el tipo de devolución.

Editar: versión más simple (pero posiblemente menos compatible) here.

+5

En lugar de #error, sería mejor #define func DEPURADO (func) – CesarB

+0

@CesarB: No estoy de acuerdo; si no hubiera error, no habría forma de darse cuenta de que sucedió algo inesperado. – foraidt

+1

mxp: La desaprobación es solo una advertencia, y por lo tanto, diría que una advertencia de que no es compatible es todo lo que necesita. –

39

Aquí es una versión simplificada de mi 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

¿Cómo '' [[deprecated]] 'sus macros en desuso? :-) –

+1

No puedo ver ninguna diferencia significativa entre esas dos respuestas. ¿Por qué lo publicaste por segunda vez? –

+3

No tiene que envolverlo en la función, por lo que está 'DEPRECATED void foo (...);' en lugar de 'DEPRECATED (void foo (...));' – dshepherd

2

Aquí es una respuesta más completa para 2018.

En estos días, una gran cantidad de herramientas le permiten no sólo marcar algo como obsoletos, pero también proporciona un mensaje. Esto le permite decirle a las personas cuando algo se desaprobó y tal vez apuntar hacia un reemplazo.

Todavía hay una gran variedad de alimentos en apoyo del compilador:

  • C++ 14 soporta [[deprecated]]/[[deprecated(message)]].
  • __attribute__((deprecated)) está soportado por GCC 4.0+ y ARM 4.1+
  • __attribute__((deprecated)) y __attribute__((deprecated(message))) está soportado para:
    • GCC 4.5+
    • Varios compiladores que se hacen pasar por GCC 4.5+ (mediante el establecimiento de __GNUC__/__GNUC_MINOR__/__GNUC_PATCHLEVEL__)
    • Compilador Intel C/C++ que se remonta a al menos 16 (no se puede confiar en __GNUC__/__GNUC_MINOR__, simplemente lo configuran para cualquier versión de GCC instalada)
    • ARM 5.6+
  • MSVC apoya __declspec(deprecated) desde 13.10 (Visual Studio 2003)
  • MSVC apoya __declspec(deprecated(message)) desde 14,0 (Visual Studio 2005)

También puede utilizar [[gnu::deprecated]] en las últimas versiones de sonido metálico en C++ 11, basado en __has_cpp_attribute(gnu::deprecated).

Tengo algunas macros en Hedley a manejar todo esto de forma automática que guardo hasta la fecha, pero la versión actual (v2) se ve así:

#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 

lo dejo como ejercicio para descubra cómo deshacerse de las macros *_VERSION_CHECK y *_HAS_ATTRIBUTE si no quiere usar Hedley (escribí Hedley en gran parte para no tener que pensar en eso regularmente).

Si utiliza GLib, puede usar las macros G_DEPRECATED y G_DEPRECATED_FOR. No son tan sólidos como los de Hedley, pero si ya usas GLib no hay nada que agregar.