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.
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 estoGRIKIFY
macro como obsoleta?– Eljay
12 oct 2022 a las 12:27
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
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 deDEPRECATED(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
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
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.
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