Последовательность спецификаторов атрибутов(с C++11)
Вводит определённые реализацией атрибуты для типов, объектов, кода и т.д.
Синтаксис
[[ список_атрибутов ]] | (с C++11) | |
[[ using пространство_имён_атрибутов : список_атрибутов ]] | (с C++17) |
где список_атрибутов — это список из нуля или более атрибутов, разделённых запятыми (возможно, с многоточием ... указывающим на развёртывание пакета параметров).
| идентификатор | (1) | |
пространство_имён_атрибутов :: идентификатор | (2) | |
идентификатор ( список_аргументов (необязательно) ) | (3) | |
пространство_имён_атрибутов :: идентификатор ( список_аргументов (необязательно) ) | (4) |
где пространство_имён_атрибутов — это идентификатор, а список_аргументов — это последовательность токенов, где скобки, квадратные скобки и фигурные скобки сбалансированы (сбалансированная_последовательность_токенов).
[[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 | (с C++17) |
Объяснение
Атрибуты предоставляют унифицированный стандартный синтаксис для расширений языка, определяемых реализацией, таких как расширения 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
}Помимо стандартных атрибутов, перечисленных ниже, реализации могут поддерживать произвольные нестандартные атрибуты с поведением, определённым реализацией. Все атрибуты, неизвестные реализации, игнорируются без выдачи ошибки.(с C++17)
| Атрибут без пространство_имён_атрибутов и пространство_имён_атрибутов, имя которого — | (с C++20) |
Стандартные атрибуты
Следующие атрибуты определены стандартом C++.
Синтаксические ошибки в стандартных атрибутах не допускаются: они не могут содержать синтаксических ошибок, должны применяться к правильной цели, и сущности в аргументах должны быть ODR-использованы.
Семантические ошибки в стандартных атрибутах также не допускаются: поведение со всеми экземплярами конкретного стандартного атрибута, удалёнными, должно было бы быть соответствующим поведением для исходной программы с присутствующим атрибутом.
[[noreturn]](C++11) | указывает, что функция не возвращает значение (спецификатор атрибута) |
[[carries_dependency]](C++11) | указывает, что цепочка зависимостей в выпуске-потреблении std::memory_order распространяется внутрь и наружу из функции(спецификатор атрибута) |
[[deprecated]](C++14)[[deprecated("reason")]](C++14) | указывает, что использование имени или сущности, объявленной с этим атрибутом, разрешено, но не рекомендуется по определённой причине (спецификатор атрибута) |
[[fallthrough]](C++17) | указывает, что переход с метки предыдущего case преднамерен и не должен быть диагностирован компилятором, который предупреждает о переходе (спецификатор атрибута) |
[[nodiscard]](C++17)[[nodiscard("reason")]](C++20) | рекомендует компилятору выдать предупреждение, если значение возврата игнорируется (спецификатор атрибута) |
[[maybe_unused]](C++17) | подавляет предупреждения компилятора о неиспользуемых сущностях, если таковые имеются (спецификатор атрибута) |
[[likely]](C++20)[[unlikely]](C++20) | указывает, что компилятор должен оптимизировать для случая, когда путь выполнения через оператор более или менее вероятен, чем любой другой путь выполнения (спецификатор атрибута) |
[[no_unique_address]](C++20) | указывает, что нестатическому члену данных не обязательно иметь адрес, отличный от всех других нестатических членов данных его класса (спецификатор атрибута) |
[[assume(expression)]](C++23) | указывает, что выражение всегда будет оцениваться как true в заданной точке (спецификатор атрибута) |
[[optimize_for_synchronized]](TM TS) | указывает, что определение функции должно быть оптимизировано для вызова из синхронизированного оператора (спецификатор атрибута) |
Примечания
Наличие каждого отдельного атрибута на конкретной платформе можно проверить с помощью препроцессорной макроса __has_cpp_attribute.
| Макросы проверки функций | Значение | Std | Функция |
|---|---|---|---|
__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++.
| DR | Применяется к | Поведение, опубликованное | Правильное поведение |
|---|---|---|---|
| CWG 2079 | C++11 |
[[ не могло появиться внутри аргумента атрибута | разрешено |
| CWG 2538 | C++11 | неясно, могут ли стандартные атрибуты быть синтаксически проигнорированы | запрещено |
| CWG 2695 | C++11 | неясно, могут ли стандартные атрибуты быть семантически проигнорированы | запрещено |
| P2156R1 | C++11 | каждый стандартный атрибут должен был появиться не более одного раза в списке атрибутов | не требуется |
См. также
__has_cpp_attribute - проверяет наличие атрибута |
|
| Документация на C для Последовательность спецификаторов атрибутов |
Внешние ссылки
| 1. |
Атрибуты в GCC. Эти атрибуты могут использоваться как [[gnu::...]], см. SO. |
| 2. | Атрибуты в Clang. |
| 3. | Атрибуты в MSVC. |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/attributes