C ++ помечен как устаревший - PullRequest
138 голосов
/ 17 ноября 2008

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

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

Ответы [ 6 ]

164 голосов
/ 17 января 2014

В 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» .

122 голосов
/ 17 ноября 2008

Это должно сработать:

#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. В этом случае вам нужно будет ввести тип возвращаемого значения.

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

50 голосов
/ 21 января 2014

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

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

21 голосов
/ 17 ноября 2008

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

void myfunc() __attribute__ ((deprecated));

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

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

4 голосов
/ 17 ноября 2008

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

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

3 голосов
/ 28 февраля 2018

Вот более полный ответ на 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, добавить нечего.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...