C ++ помечен как устаревший


147

У меня есть метод в интерфейсе, который я хочу осудить с помощью портативного C ++. Когда я погуглил для этого, все, что я получил, было определенным решением Microsoft; #pragma устарела и __declspec (устарела) .

Вторым призовым решением было бы определение MSVC и GCC.
Спасибо

Ответы:


193

В C ++ 14 вы можете пометить функцию как устаревшую, используя [[deprecated]]атрибут (см. Раздел 7.6.5 [dcl.attr.deprecated]).

Атрибут-маркер deprecated можно использовать для имен меток и юридических лиц, использование которых по- прежнему допускается, но не рекомендуется для какой - то причине.

Например, следующая функция fooустарела:

[[deprecated]]
void foo(int);

Можно предоставить сообщение, которое описывает, почему имя или объект устарели:

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

Сообщение должно быть строковым литералом.

Дополнительные сведения см. В разделе «Маркировка как устаревшая в C ++ 14» .


Можете ли вы использовать [[не рекомендуется]] в макросе?
Даниэль Райан

2
@Zammbi Вы должны это сделать, так как макрос обрабатывается препроцессором перед компиляцией. [[устарело]] должно появиться (и позволить компилятору выводить связанные предупреждения), где макрос оценивается.
Флориан Кастеллан

129

Это должно сделать трюк:

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

Однако вы столкнетесь с проблемами, если тип возвращаемого значения функции будет иметь запятую в имени, например, так std::pair<int, int>как это будет интерпретироваться препроцессором как передача 2 аргументов макросу DEPRECATED. В этом случае вам нужно будет определить тип возвращаемого значения.

Изменить: более простая (но, возможно, менее широко совместимая) версия здесь .


6
Вместо #error было бы лучше #define DEPRECATED (func) func
CesarB

1
mxp: Устаревание - это всего лишь предупреждение, и поэтому я бы сказал, что все, что вам нужно, это предупреждение о том, что оно не поддерживается.
Леон Тиммерманс

1
Да, я бы пошел на «#warning Вам нужно реализовать DEPRECATED для этого компилятора», или что-то подобное. Если это невозможно, то портер может #define DEPRECATED (FUNC) FUNC и жить без него.
Стив Джессоп

2
К сожалению, в C ++ нет стандартного способа вывести предупреждение о компиляции: P #pragma сообщение будет делать.
Майкл Плакингс

3
Синтаксис атрибута gcc позволяет атрибуту находиться в тех же местах, что и __declspec(deprecated)сейчас, поэтому макрос можно упростить.
bames53

57

Вот упрощенная версия моего ответа 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);

Смотрите также:


17
Как [[deprecate]]твои устаревшие макросы? :-)
graham.reeds

3
Я не вижу существенной разницы между этими двумя ответами. Почему вы опубликовали это во второй раз?
Томаш Зато - Восстановить Монику

4
Вам не нужно оборачивать его вокруг функции, так что DEPRECATED void foo(...);вместо этогоDEPRECATED(void foo(...));
dshepherd

12
Вы должны были отредактировать свой ответ за 2008 год, а не публиковать новый.
Яков Галка

4
Это может быть не так широко совместимо, как мой другой ответ, поэтому я добавил это отдельно.
Майкл Плакингс

22

В GCC вы можете объявить вашу функцию с устаревшим атрибутом следующим образом:

void myfunc() __attribute__ ((deprecated));

Это вызовет предупреждение во время компиляции, когда эта функция используется в файле .c.

Вы можете найти дополнительную информацию в разделе «Диагностические прагмы» по адресу http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html.


8

Вот более полный ответ на 2018 год.

В наши дни многие инструменты позволяют не только пометить что-то как устаревшее, но и предоставить сообщение. Это позволяет вам сказать людям, когда что-то устарело, и, возможно, указать им на замену.

Поддержка компилятора по-прежнему велика:

  • C ++ 14 поддерживает [[deprecated]]/ [[deprecated(message)]].
  • __attribute__((deprecated)) поддерживается GCC 4.0+ и ARM 4.1+
  • __attribute__((deprecated))и __attribute__((deprecated(message)))поддерживается для:
    • GCC 4.5+
    • Несколько компиляторов, которые маскируются под GCC 4.5+ (путем установки __GNUC__/ __GNUC_MINOR__/ __GNUC_PATCHLEVEL__)
    • Компилятор Intel C / C ++ возвращается по крайней мере к 16 (вы не можете доверять __GNUC__/ __GNUC_MINOR__, они просто устанавливают для него установленную версию GCC)
    • ARM 5.6+
  • MSVC поддерживает __declspec(deprecated)с 13.10 (Visual Studio 2003)
  • MSVC поддерживает __declspec(deprecated(message))с 14.0 (Visual Studio 2005)

Вы также можете использовать [[gnu::deprecated]]в последних версиях Clang в C ++ 11, на основе __has_cpp_attribute(gnu::deprecated).

У меня есть несколько макросов в Hedley для автоматической обработки всего этого, которые я постоянно обновляю, но текущая версия (v2) выглядит следующим образом:

#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

Я оставлю его в качестве упражнения , чтобы выяснить , как избавиться от *_VERSION_CHECKи *_HAS_ATTRIBUTEмакросы , если вы не хотите использовать Хедли (я писал Хедли в основном , так что я не должен думать о том, что на регулярной основе).

Если вы используете GLib, вы можете использовать G_DEPRECATEDи G_DEPRECATED_FORмакросы. Они не такие надежные, как у Hedley, но если вы уже используете GLib, добавить нечего.


4

При работе с переносимыми проектами почти неизбежно, что в какой-то момент вам понадобится раздел предварительно обработанных альтернатив для ряда платформ. #ifdef это #ifdef это и так далее.

В таком разделе вы вполне могли бы условно определить способ устаревания символов. Обычно я предпочитаю определять макрос «предупреждение», так как большинство наборов инструментов поддерживают пользовательские предупреждения компилятора. Затем вы можете перейти к определенному макросу предупреждений об устаревании и т. Д. Для платформ, поддерживающих выделенные методы устаревания, вы можете использовать это вместо предупреждений.


1

Для Intel Compiler v19.0 используйте это, __INTEL_COMPILERчтобы оценить 1900:

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

Работает для следующих языковых уровней:

  • Поддержка C ++ 17 (/ Qstd = c ++ 17)
  • Поддержка C ++ 14 (/ Qstd = c ++ 14)
  • Поддержка C ++ 11 (/ Qstd = c ++ 11)
  • Поддержка C11 (/ Qstd = c11)
  • Поддержка C99 (/ Qstd = c99)

Компилятор Intel имеет ошибку, заключающуюся в том, что он не поддерживает [[deprecated]]атрибут некоторых языковых элементов, как это делают все другие компиляторы. Например, скомпилируйте v6.0.0 (замечательно превосходной) библиотеки {fmtlib / fmt} на GitHub с Intel Compiler v19.0. Это сломается. Затем посмотрите исправление в коммите GitHub .


Это неверно; Атрибуты C ++ не работают в режиме C на ICC. Пример . __attribute__((deprecated))OTOH, работает на C и C ++, возвращаясь, по крайней мере, к ICC 13.0, возможно, намного дальше (Intel стремится не документировать подобные вещи, поэтому я не уверен).
nemequ
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.