Последовательность спецификаторов атрибутов (since C++11)
Вводит атрибуты, поведение которых определяется реализацией, для типов, объектов, кода и т. д.
Синтаксис
[[ attribute-list ]] | (since C++11) | |
[[ using attribute-namespace : attribute-list ]] | (since C++17) |
где attribute-list — последовательность из нуля или более элементов attribute, разделённых запятыми (возможно, заканчивающаяся многоточием ..., обозначающим раскрытие пакета параметров)
| identifier | (1) | |
attribute-namespace :: identifier | (2) | |
identifier ( argument-list (необязательно) ) | (3) | |
attribute-namespace :: identifier ( argument-list (необязательно) ) | (4) |
где attribute-namespace — это identifier, а argument-list — последовательность токенов со сбалансированными круглыми, квадратными и фигурными скобками (balanced-token-seq).
[[noreturn]].[[gnu::unused]].[[deprecated("because")]].| Если [[using CC: opt(1), debug]] // same as [[CC::opt(1), CC::debug]] [[using CC: CC::opt(1)]] // error: cannot combine using and scoped attribute | (since C++17) |
| Если каждый элемент спецификатора атрибута начинается с | (since C++26) |
Пояснение
Атрибуты предоставляют единый стандартный синтаксис для расширений языка, поведение которых определяется реализацией, таких как расширения языков GNU и IBM __attribute__((...)), расширение Microsoft __declspec() и т. д.
Атрибут можно использовать почти в любом месте программы на C++ и применять почти ко всему: к типам, переменным, функциям, именам, блокам кода и целым единицам трансляции. Однако каждый конкретный атрибут допустим только там, где его разрешает реализация: [[expect_true]] мог бы быть атрибутом, который можно использовать только с if, но не с объявлением класса. [[omp::parallel()]] мог бы быть атрибутом, применимым к блоку кода или циклу for, но не к типу int и т. д. (обратите внимание, что эти два атрибута — вымышленные примеры; стандартные и некоторые нестандартные атрибуты перечислены ниже).
В объявлениях атрибуты могут располагаться как перед объявлением целиком, так и непосредственно после имени объявляемой сущности; в последнем случае они объединяются. В большинстве других ситуаций атрибуты применяются к непосредственно предшествующей сущности.
Спецификатор alignas является частью последовательности спецификаторов атрибутов, хотя его синтаксис отличается. Он может располагаться там же, где и атрибуты [[...]], и сочетаться с ними (при условии, что используется в месте, где разрешён alignas).
Два следующих друг за другом токена левой квадратной скобки ([[) могут встречаться только при введении спецификатора атрибута или внутри аргумента атрибута.
void f()
{
int y[3];
y[[] { return 0; }()] = 1; // error
int i [[cats::meow([[]])]]; // OK
}
Помимо перечисленных ниже стандартных атрибутов, реализации могут поддерживать произвольные нестандартные атрибуты с поведением, определяемым реализацией. Все атрибуты, неизвестные реализации, игнорируются без ошибки.(since C++17)
| Атрибут без attribute-namespace, а также attribute-namespace, имя которого равно | (since C++20) |
Стандартные атрибуты
Следующие атрибуты определены стандартом C++.
Стандартные атрибуты нельзя синтаксически игнорировать: они не должны содержать синтаксических ошибок, должны применяться к правильной цели, а сущности в аргументах должны быть использованы по правилу ODR.
Стандартные атрибуты нельзя игнорировать и семантически: поведение, полученное после удаления всех экземпляров конкретного стандартного атрибута, должно соответствовать стандарту для исходной программы с этим атрибутом.
[[noreturn]](C++11) | указывает, что функция не возвращает управление (спецификатор атрибута) |
|
(C++11)(удалён в C++26) | указывает, что цепочка зависимостей в модели памяти release-consume std::memory_order проходит через функцию в обоих направлениях(спецификатор атрибута) |
[[deprecated]][[deprecated("reason")]](C++14)(C++14) | указывает, что использование имени или сущности, объявленной с этим атрибутом, разрешено, но не рекомендуется по некоторой причине (спецификатор атрибута) |
[[fallthrough]](C++17) | указывает, что переход к следующей метке case из предыдущей метки case является намеренным и не должен вызывать предупреждение компилятора, если тот предупреждает о таком переходе (спецификатор атрибута) |
[[maybe_unused]](C++17) | подавляет предупреждения компилятора о неиспользуемых сущностях, если таковые имеются (спецификатор атрибута) |
|
(C++17)(C++20) | побуждает компилятор выдать предупреждение, если возвращаемое значение отбрасывается (спецификатор атрибута) |
|
(C++20)(C++20) | указывает, что компилятору следует оптимизировать программу для случая, когда путь выполнения через оператор более или менее вероятен, чем любой другой путь выполнения (спецификатор атрибута) |
|
(C++20) | указывает, что нестатический член данных не обязан иметь адрес, отличный от адресов всех остальных нестатических членов данных своего класса (спецификатор атрибута) |
[[assume(expression)]](C++23) | указывает, что выражение всегда будет вычисляться в true в заданной точке(спецификатор атрибута) |
[[indeterminate]](C++26) | указывает, что объект имеет неопределённое значение, если он не инициализирован (спецификатор атрибута) |
|
(TM TS) | указывает, что определение функции следует оптимизировать для вызова из синхронизированного оператора (спецификатор атрибута) |
Примечания
Наличие каждого отдельного атрибута на заданной платформе можно проверить с помощью макроса препроцессора __has_cpp_attribute.
| Макрос проверки возможностей | Значение | Стандарт | Возможность |
|---|---|---|---|
__cpp_attributes | 200809L | (C++11) | Атрибуты |
__cpp_namespace_attributes | 201411L | (C++17) | Атрибуты для пространств имён |
Пример
[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]]
inline int f(); // declare f with four attributes
[[gnu::always_inline, gnu::const, gnu::hot, nodiscard]]
int f(); // same as above, but uses a single attr specifier that contains four attributes
// C++17:
[[using gnu : const, always_inline, hot]] [[nodiscard]]
int f[[gnu::always_inline]](); // an attribute may appear in multiple specifiers
int f() { return 0; }
int main() {}
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были ретроактивно применены к ранее опубликованным стандартам C++.
| Отчёт об ошибке | Применяется к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| CWG 2079 | C++11 |
[[ нельзя было использовать внутри аргумента атрибута | разрешено |
| CWG 2538 | C++11 | не было ясно, можно ли синтаксически игнорировать стандартные атрибуты | запрещено |
| CWG 2695 | C++11 | не было ясно, можно ли семантически игнорировать стандартные атрибуты | запрещено |
| P2156R1 | C++11 | каждый стандартный атрибут должен был встречаться в attribute-list не более одного раза | не обязательно |
См. также
__has_cpp_attribute — проверяет наличие атрибута |
|
| Документация по C для последовательности спецификаторов атрибутов |
Внешние ссылки
| 1. |
Атрибуты в GCC. Эти атрибуты можно использовать как [[gnu::...]], см. Stack Overflow. |
| 2. | Атрибуты в Clang. |
| 3. | Атрибуты в MSVC. |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/attributes