Marca C ++ como descontinuada

147

Eu tenho um método em uma interface que eu quero descontinuar com C ++ portátil. Quando pesquisei por isso, tudo o que obtive foi uma solução específica da Microsoft; #pragma descontinuado e __declspec (descontinuado) .

Uma solução para o segundo prêmio seria definir uma solução MSVC e GCC.
obrigado

Diederik
fonte

Respostas:

193

No C ++ 14, você pode marcar uma função como obsoleta usando o [[deprecated]]atributo (consulte a seção 7.6.5 [dcl.attr.deprecated]).

O token de atributo deprecated pode ser usado para marcar nomes e entidades cujo uso ainda é permitido, mas é desencorajado por algum motivo.

Por exemplo, a seguinte função fooestá obsoleta:

[[deprecated]]
void foo(int);

É possível fornecer uma mensagem que descreva por que o nome ou a entidade foi preterido:

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

A mensagem deve ser uma string literal.

Para mais detalhes, consulte “Marcando como Descontinuado no C ++ 14” .

Joseph Mansfield
fonte
Você pode usar [[obsoleto]] em uma macro?
Daniel Ryan
2
@ Zammbi Você deve conseguir, pois a macro é tratada pelo pré-processador antes da compilação. [[obsoleto]] deve aparecer (e deixar que o compilador produza avisos relacionados) onde a macro é avaliada.
Florian Castellane
129

Isso deve fazer o truque:

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

No entanto, você encontrará problemas se um tipo de retorno de função tiver vírgulas em seu nome, por exemplo, std::pair<int, int>pois isso será interpretado pelo pré-processador como passando 2 argumentos para a macro DEPRECATED. Nesse caso, você teria que digitar o tipo de retorno.

Editar: versão mais simples (mas possivelmente menos amplamente compatível) aqui .

Michael Platings
fonte
6
Em vez de #error, seria melhor para #define DEPRECADO (func) func
CesarB
1
mxp: A descontinuação é apenas um aviso e, portanto, eu diria que um aviso de que não é suportado é tudo que você precisa.
Leon Timmermans
1
Sim, eu usaria "#warning Você precisa implementar DEPRECATED para este compilador", ou algo assim. Se isso for impossível, o porteiro pode # definir FUNC DEPRESADO (FUNC) e viver sem ele.
17608 Steve Jessop
2
Infelizmente, não há uma maneira padrão de emitir um aviso de compilação em C ++: a mensagem de pragma P # terá que fazer.
Michael Platings
3
A sintaxe do atributo do gcc permite que o atributo esteja nos mesmos lugares que __declspec(deprecated)agora, para que a macro possa ser simplificada.
bames53
57

Aqui está uma versão simplificada da minha resposta 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);

Veja também:

Michael Platings
fonte
17
Como [[deprecate]]suas macros obsoletas? :-)
graham.reeds
3
Não vejo diferença significativa entre essas duas respostas. Por que você publicou uma segunda vez?
Tomáš Zato - Reinstala Monica
4
Você não tem que envolvê-la em torno da função por isso é DEPRECATED void foo(...);em vez deDEPRECATED(void foo(...));
dshepherd
12
Você deveria ter editado sua resposta de 2008 em vez de postar uma nova.
Yakov Galka
4
Isso pode não ser tão amplamente compatível quanto a minha outra resposta, portanto, eu adicionei isso separadamente.
Michael Platings
22

No GCC, você pode declarar sua função com o atributo obsoleto da seguinte forma:

void myfunc() __attribute__ ((deprecated));

Isso disparará um aviso em tempo de compilação quando essa função é usada em um arquivo .c.

Você pode encontrar mais informações em "Pragmas de diagnóstico" em http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html

Terje Mikal
fonte
8

Aqui está uma resposta mais completa para 2018.

Atualmente, muitas ferramentas permitem não apenas marcar algo como obsoleto, mas também fornecer uma mensagem. Isso permite que você diga às pessoas quando algo foi descontinuado e talvez as aponte para uma substituição.

Ainda há muita variedade no suporte ao compilador:

  • O C ++ 14 suporta [[deprecated]]/ [[deprecated(message)]].
  • __attribute__((deprecated)) é suportado pelo GCC 4.0+ e ARM 4.1+
  • __attribute__((deprecated))e __attribute__((deprecated(message)))é suportado por:
    • GCC 4.5+
    • Vários compiladores que se disfarçam como GCC 4.5+ (configurando __GNUC__/ __GNUC_MINOR__/ __GNUC_PATCHLEVEL__)
    • Compilador Intel C / C ++ com pelo menos 16 (você não pode confiar em __GNUC__/ __GNUC_MINOR__, eles apenas o definem para qualquer versão do GCC instalada)
    • ARM 5.6+
  • O MSVC suporta __declspec(deprecated)desde 13.10 (Visual Studio 2003)
  • O MSVC suporta __declspec(deprecated(message))desde 14.0 (Visual Studio 2005)

Você também pode usar [[gnu::deprecated]]nas versões recentes do clang no C ++ 11, com base em __has_cpp_attribute(gnu::deprecated).

Eu tenho algumas macros no Hedley para lidar com tudo isso automaticamente, que eu mantenho atualizado, mas a versão atual (v2) é assim:

#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

Vou deixar isso como um exercício para descobrir como se livrar das macros *_VERSION_CHECKe *_HAS_ATTRIBUTEse você não quiser usar o Hedley (eu escrevi o Hedley amplamente para não precisar pensar nisso regularmente).

Se você usar GLib, você pode usar o G_DEPRECATEDe G_DEPRECATED_FORmacros. Eles não são tão robustos quanto os da Hedley, mas se você já usa o GLib, não há nada a acrescentar.

nemequ
fonte
4

Lidar com projetos portáteis é quase inevitável que em algum momento você precise de uma seção de alternativas pré-processadas para uma variedade de plataformas. #ifdef isso #ifdef isso e assim por diante.

Nessa seção, você poderia muito bem definir condicionalmente uma maneira de descontinuar os símbolos. Minha preferência é geralmente definir uma macro de "aviso", já que a maioria das cadeias de ferramentas oferece suporte a avisos personalizados do compilador. Em seguida, você pode continuar com uma macro de aviso específica para descontinuação, etc. Para as plataformas que suportam métodos de descontinuação dedicados, você pode usá-lo em vez de avisos.

Sharkin
fonte
1

Para o Intel Compiler v19.0, use-o como __INTEL_COMPILERavaliado para 1900:

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

Funciona para os seguintes níveis de idioma:

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

O Intel Compiler possui o que parece um bug, pois não suporta o [[deprecated]]atributo em certos elementos de linguagem que todos os outros compiladores. Por exemplo, compile a v6.0.0 da biblioteca {fmtlib / fmt} (extraordinariamente excelente) no GitHub com o Intel Compiler v19.0. Isso vai quebrar. Então veja a correção no commit do GitHub .

Contango
fonte
Isso está incorreto; Os atributos C ++ não funcionam no modo C no ICC. Exemplo . __attribute__((deprecated)), OTOH, trabalha em C e C ++ desde pelo menos a ICC 13.0, provavelmente muito mais longe (a Intel tende a não documentar esse tipo de coisa, então não tenho certeza).
nemequ 2/03