Знак С++ как устаревший
У меня есть метод в интерфейсе, который я хочу использовать с переносимым C++.
Когда я погуглил для этого, все, что я получил, было определенным решением Microsoft; #pragma устарела и __declspec (устарела).
Вторым призовым решением было бы определение MSVC и GCC.
Спасибо
Ответы
Ответ 1
В С++ 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);
Сообщение должно быть строковым литералом.
Для получения дополнительной информации см. "Маркировка как устаревшая в С++ 14" .
Ответ 2
Это должно сделать трюк:
#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. В этом случае вам придется ввести тип возвращаемого типа.
Изменить: более простая (но, возможно, менее широко совместимая) версия здесь.
Ответ 3
Вот упрощенная версия моего ответа 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);
Смотрите также:
Ответ 4
В GCC вы можете объявить свою функцию атрибутом, устаревшим следующим образом:
void myfunc() __attribute__ ((deprecated));
Это вызовет предупреждение времени компиляции, когда эта функция используется в файле .c.
Дополнительную информацию см. в разделе "Диагностические прагмы" в
http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html
Ответ 5
Вот более полный ответ на 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)
.
У меня есть несколько макросов в Хедли для автоматической обработки всего этого, что я постоянно обновляю, но текущая версия (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, добавить нечего.
Ответ 6
Работа с портативными проектами почти неизбежна, что вам в какой-то момент нужен раздел предварительно обработанных альтернатив для ряда платформ. #ifdef это #ifdef и т.д.
В таком разделе вы вполне можете условно определить способ обесценивания символов. Мое предпочтение обычно заключается в определении макроса "предупреждения", поскольку большинство программных цепочек поддерживают специальные предупреждения компилятора. Затем вы можете продолжать использовать специальный предупреждающий макрос для устаревания и т.д.
Для платформ, поддерживающих специальные методы устаревания, вы можете использовать это вместо предупреждений.
Ответ 7
Для Intel Compiler v19.0 используйте это, поскольку __INTEL_COMPILER
оценивается как 1900
:
# if defined(__INTEL_COMPILER)
# define DEPRECATED [[deprecated]]
# endif
Работает для следующих языковых уровней:
- Поддержка С++ 17 (/Qstd = c ++ 17)
- Поддержка С++ 14 (/Qstd = c ++ 14)
- Поддержка С++ 11 (/Qstd = c ++ 11)
- Поддержка C11 (/Qstd = c11)
- Поддержка C99 (/Qstd = c99)
Компилятор Intel имеет ошибку, заключающуюся в том, что он не поддерживает атрибут [[deprecated]]
в определенных языковых элементах, что делают все другие компиляторы. Например, скомпилируйте v6.0.0 (удивительно превосходной) библиотеки {fmtlib/fmt} на GitHub с помощью Intel Compiler v19.0. Это сломается. Затем посмотрите исправление в коммите GaHub.