Атрибут deprecated в С++14

в 6:32, , рубрики: c++, C++14, Блог компании Инфопульс Украина, Программирование

Нормальным развитием любого кода является устаревание отдельных его частей (функций, классов и т.д.) и планомерное удаление их из проекта для снижения сложности и повышения безопасности кода. Просто убрать что-то обычно является плохой идеей — это может резко сломать какой-нибудь компонент, использующий удаляемую сущность. Хорошей практикой является пометка устаревшего кода каким-либо способом, который даст возможность использующим его программистам узнать о том, что он запланирован к удалению. (Прим. переводчика — Microsoft для этого изобрела свой велосипед, а ещё люди иногда пользовались #pragma message).

Новый стандарт С++14 вводит атрибут deprecated для пометки устаревших сущностей, планируемых к удалению в дальнейшем. Компилятор может выводить предупреждения при любой попытке их использования. Синтаксис принципиально новый для С++: атрибуты предполагается писать в виде списка через запятую, внутри двойных квадратных скобок. Вот так выглядит функция, помеченная как deprecated:

[[deprecated]]
void foo() {}

int main() {
	foo(); // в этом месте компилятор выведет предупреждение
}


Другие возможные атрибуты: noreturn, carries_dependency, alignas

Код выше, будучи скомпилированным последним билдом clang, выдаёт следующее сообщение на этапе компиляции:

warning: 'foo' is deprecated [-Wdeprecated-declarations]
        foo();
        ^
note: 'foo' has been explicitly marked deprecated here
void foo() {}
     ^

Также возможно вывести собственное сообщение:

[[deprecated("use bar instead")]]
void foo() {}
This gives the following warning instead:

warning: 'foo' is deprecated: use bar instead [-Wdeprecated-declarations]
        foo();
        ^
note: 'foo' has been explicitly marked deprecated here
void foo() {}
     ^

Атрибут deprecated также применим к классам, typedef-ам, переменным, не статическим членам данных, перечислениям и шаблонам. Вот пара примеров:

// помечаем функцию
[[deprecated]]
void foo();

// помечаем переменную
[[deprecated]]
int x;

// помечаем только одну переменную в списке определяемых
int y [[deprecated]], z;

// помечаем параметр функции
int triple([[deprecated]] int x);

// помечаем класс или структуру
class [[deprecated]] my_class {
	public:
		// помечаем член класса
		[[deprecated]] int member;
};

// помечаем перечисление
enum [[deprecated]] animals {
	CAT, DOG, MOUSE
};

// помечаем typedef
[[deprecated]]
typedef int type;

// помечаем шаблон
template <typename T> class templ;

template <>
class [[deprecated]] templ<int> {};

Для тех, кто отмечает бросающуюся в глаза неконсистентность размещения атрибутов (к примеру их использование после ключевых слов class и enum) скажу, что это для того, чтобы можно было отличить пометку самого типа от пометки переменной этого типа. Например, следующее объявление помечает переменную, но не сам класс:

[[deprecated]] class C { } c;

Атрибут deprecated может быть указан только в одном определении некоторой сущности, все следующие объявления без данного атрибута не снимают атрибут deprecated. Лучше всего помещать атрибут в заголовочный файл — этим вы подскажете всем пользователям, что сущность устарела и будет удалена.

Атрибут поддерживается начиная с Clang 3.4 и GCC 4.9.

Примечания переводчика: атрибуты, появившиеся ещё в стандарте С++11 подавали большие надежды — новая возможность добавлять метаданные к функциям, классам и другим вещам потенциально открывали большие возможности для мета-программирования, рефлексии, тестирования — в конце-концов C# и Python уже доказали реальную пользу подобных инструментов языка и лично мне хотелось верить, что и С++ получит в будущем что-то подобное. К сожалению, первые введённые атрибуты (noreturn, carries_dependency, alignas) давали как-то маловато пользы, что портило положительное впечатление от фичи. deprecated — первый, на мой взгляд, реально простой, понятный и нужный каждому атрибут. Хочется верить, что это шаг на пути к дальнейшим фичам языка на основе атрибутов.

Автор: tangro

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js