¿Cómo puedo marcar un método de clase de C++ como obsoleto?

7 minutos de lectura

Avatar de usuario de Diederik
Diederik

Tengo un método en una interfaz de C++ que quiero desaprobar, con código portátil.

Cuando busqué esto en Google, todo lo que obtuve fue una solución específica de Microsoft; #pragma deprecated y __declspec(deprecated).

Si no hay disponible una solución de obsolescencia general o totalmente portátil, aceptaré como “solución de segundo premio” una que se pueda usar con varios compiladores específicos, como MSVC y GCC.

Avatar de usuario de Joseph Mansfield
jose mansfield

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

El atributo-token deprecated se puede usar para marcar nombres y entidades cuyo uso todavía está permitido, pero se desaconseja por algún motivo.

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

[[deprecated]]
void foo(int);

Es posible proporcionar un mensaje que describa por qué el nombre o la entidad quedaron obsoletos:

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

El mensaje debe ser un literal de cadena.

Para más detalles, consulte “Marcar como obsoleto en C++ 14”.

  • Puedes usar [[deprecated]]en una macro?

    –Daniel Ryan

    19 de noviembre de 2015 a las 3:20

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

    – Florián Castellane

    3 de noviembre de 2016 a las 15:26

  • ¿Y qué hay de C++ 11?

    – warchantua

    21 de enero de 2021 a las 14:11

  • #define GRIKIFY(x) if (x) Grike(x) como puedo marcar esto GRIKIFY macro como obsoleta?

    – Eljay

    12 oct 2022 a las 12:27

Avatar de usuario de Michael Platings
Revestimientos de Michael

Esto debería funcionar:

#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, encontrará problemas si el tipo de retorno de una función tiene 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ía que escribir def el tipo de retorno.

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

  • En lugar de #error, sería mejor #define DEPRECATED(func) func

    – CesarB

    17 de noviembre de 2008 a las 10:41

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

    – León Timmermans

    17 de noviembre de 2008 a las 15:45

  • Sí, optaría por “#advertencia, debe implementar DEPRECATED para este compilador”, o algo así. Si eso es imposible, entonces el portero puede #definir DEPRECATED(FUNC) FUNC, y vivir sin él.

    –Steve Jessop

    17 de noviembre de 2008 a las 16:16

  • Desafortunadamente, no hay una forma estándar de generar una advertencia de compilación en C ++: el mensaje P #pragma tendrá que funcionar.

    – Michael Platings

    17 de noviembre de 2008 a las 18:04

  • La sintaxis de atributos de gcc permite que el atributo esté en los mismos lugares que __declspec(deprecated) ahora, para que la macro se pueda simplificar.

    – bames53

    29 de noviembre de 2012 a las 17:06

Avatar de usuario de Michael Platings
Revestimientos de Michael

Aquí hay una versión simplificada de mi respuesta de 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);

Ver también:

  • Cómo [[deprecate]] sus macros obsoletas? 🙂

    – graham.reeds

    13 oct 2015 a las 12:39

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

    – Tomáš Zato

    13 de noviembre de 2015 a las 14:29


  • No tiene que envolverlo alrededor de la función para que sea DEPRECATED void foo(...); en lugar de DEPRECATED(void foo(...));

    – pastor

    25 de enero de 2016 a las 17:25

  • Debería haber editado su respuesta de 2008 en lugar de publicar una nueva.

    – Yakov Galka

    24 de julio de 2016 a las 13:38

  • Es posible que esto no sea tan compatible como mi otra respuesta, por lo tanto, lo agregué por separado.

    – Michael Platings

    13 de octubre de 2016 a las 9:04

Avatar de usuario de Terje Mikal
Terje Mikal

En GCC puede declarar su función con el atributo en desuso de esta manera:

void myfunc() __attribute__ ((deprecated));

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

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

avatar de usuario de nemequ
nemequ

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

En estos días, muchas herramientas le permiten no solo marcar algo como obsoleto, sino también proporcionar un mensaje. Esto le permite informar a las personas cuando algo quedó obsoleto y tal vez orientarlos hacia un reemplazo.

Todavía hay mucha variedad en el soporte del compilador:

  • C ++ 14 admite [[deprecated]]/[[deprecated(message)]].
  • __attribute__((deprecated)) es compatible con GCC 4.0+ y ARM 4.1+
  • __attribute__((deprecated)) y __attribute__((deprecated(message))) es compatible con:
    • CCG 4.5+
    • Varios compiladores que se hacen pasar por GCC 4.5+ (configurando __GNUC__/__GNUC_MINOR__/__GNUC_PATCHLEVEL__)
    • Compilador Intel C/C++ que se remonta al menos a 16 (no puede confiar __GNUC__/__GNUC_MINOR__simplemente lo configuran en cualquier versión de GCC que esté instalada)
    • BRAZO 5.6+
  • Soportes de MSVC __declspec(deprecated) desde 13.10 (Visual Studio 2003)
  • Soportes de MSVC __declspec(deprecated(message)) desde 14.0 (Visual Studio 2005)

También puedes usar [[gnu::deprecated]] en versiones recientes de clang en C++11, basado en __has_cpp_attribute(gnu::deprecated).

Tengo algunas macros en Hedley para manejar todo esto automáticamente que mantengo actualizado, 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 dejaré como ejercicio para averiguar cómo deshacerse de la *_VERSION_CHECK y *_HAS_ATTRIBUTE macros si no quieres usar Hedley (escribí Hedley en gran medida para no tener que pensar en eso regularmente).

Si usa GLib, puede usar el G_DEPRECATED y G_DEPRECATED_FOR macros No son tan robustos como los de Hedley, pero si ya usas GLib no hay nada que agregar.

avatar de usuario de sharkin
tiburones

Al tratar con proyectos portátiles, es casi inevitable que en algún momento necesite una sección de alternativas preprocesadas para una variedad de plataformas. #ifdef esto #ifdef aquello y así sucesivamente.

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

Para Intel Compiler v19.0, use esto como __INTEL_COMPILER evalúa a 1900:

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

Funciona para los siguientes niveles de idioma:

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

Intel Compiler tiene lo que parece un error en el sentido de que no admite el [[deprecated]] atributo en ciertos elementos del lenguaje que hacen todos los demás compiladores. Por ejemplo, compile v6.0.0 de (notablemente excelente) {fmtlib/fmt} biblioteca en GitHub con Intel Compiler v19.0. Se romperá. Entonces mira el corrección en la confirmación de GitHub.

  • Esto es incorrecto; Los atributos de C++ no funcionan en modo C en ICC. Ejemplo. __attribute__((deprecated))OTOH, funciona en C y C ++ desde al menos ICC 13.0, probablemente mucho más (Intel tiende a no documentar este tipo de cosas, así que no puedo estar seguro).

    – nemequ

    2 de marzo de 2020 a las 19:07

¿Ha sido útil esta solución?