Attribute specifier sequence (since C++11)
Вводит определяемые реализацией атрибуты для типов, объектов, кода и т.д.
Содержание |
Синтаксис
[[
список-атрибутов
]]
|
(начиная с C++11) | ||||||||
[[
using
пространство-имён-атрибутов
:
список-атрибутов
]]
|
(начиная с C++17) | ||||||||
где
attribute-list
представляет собой разделённый запятыми список из нуля или более
attribute
ов (возможно, заканчивающийся многоточием
...
, обозначающим
pack expansion
)
| identifier | (1) | ||||||||
attribute-namespace
::
identifier
|
(2) | ||||||||
identifier
(
argument-list
(необязательно)
)
|
(3) | ||||||||
attribute-namespace
::
identifier
(
argument-list
(необязательно)
)
|
(4) | ||||||||
где attribute-namespace является идентификатором , а argument-list представляет собой последовательность токенов, в которой круглые, квадратные и фигурные скобки сбалансированы ( balanced-token-seq ).
|
Если
[[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
specifier
является частью последовательности спецификаторов атрибутов, хотя имеет другой синтаксис. Он может появляться там, где появляются атрибуты
[[...]]
и может смешиваться с ними (при условии, что он используется там, где
alignas
разрешён).
Два последовательных токена левой квадратной скобки (
[[
) могут появляться только при введении спецификатора атрибута или внутри аргумента атрибута.
void f() { int y[3]; y[[] { return 0; }()] = 1; // ошибка int i [[cats::meow([[]])]]; // OK }
Помимо стандартных атрибутов, перечисленных ниже, реализации могут поддерживать произвольные нестандартные атрибуты с поведением, определяемым реализацией. Все атрибуты, неизвестные реализации, игнорируются без выдачи ошибки. (начиная с C++17)
|
Атрибут без
attribute-namespace
и атрибут с
attribute-namespace
, имя которого является либо
|
(since C++20) |
Стандартные атрибуты
Следующие атрибуты определены стандартом C++.
Стандартные атрибуты не могут быть синтаксически проигнорированы: они не могут содержать синтаксических ошибок, должны применяться к корректной цели, и сущности в аргументах должны быть ODR-use .
Стандартные атрибуты также не могут быть семантически проигнорированы: поведение со всеми экземплярами конкретного стандартного атрибута удаленными должно было бы быть соответствующим поведению для исходной программы с присутствующим атрибутом.
[[
noreturn
]]
(C++11)
|
указывает, что функция не возвращает управление
(спецификатор атрибута) |
[[
carries_dependency
]]
(C++11)
(удален в C++26)
|
указывает, что цепочка зависимостей в release-consume
std::memory_order
распространяется внутрь и наружу функции
(спецификатор атрибута) |
[[
deprecated
]]
[[
deprecated
("
reason
")]]
(C++14)
(C++14)
|
указывает, что использование имени или сущности, объявленной с этим атрибутом, разрешено, но не рекомендуется по некоторой
причине
(спецификатор атрибута) |
[[
fallthrough
]]
(C++17)
|
указывает, что переход на следующую метку case является преднамеренным и не должен диагностироваться компилятором, который предупреждает о таких переходах
(спецификатор атрибута) |
[[
maybe_unused
]]
(C++17)
|
подавляет предупреждения компилятора о неиспользуемых сущностях, если таковые имеются
(спецификатор атрибута) |
|
побуждает компилятор выдавать предупреждение, если возвращаемое значение игнорируется
(спецификатор атрибута) |
|
|
указывает, что компилятор должен оптимизировать случай, когда путь выполнения через оператор более или менее вероятен, чем любой другой путь выполнения
(спецификатор атрибута) |
|
[[
no_unique_address
]]
(C++20)
|
указывает, что нестатический член данных не обязан иметь адрес, отличный от всех других нестатических членов данных своего класса
(спецификатор атрибута) |
[[
assume
(
expression
)]]
(C++23)
|
указывает, что
выражение
всегда будет вычисляться в
true
в данной точке
(спецификатор атрибута) |
[[
indeterminate
]]
(C++26)
|
указывает, что объект имеет неопределенное значение, если он не инициализирован
(спецификатор атрибута) |
|
(TM TS)
|
указывает, что определение функции должно быть оптимизировано для вызова из
synchronized statement
(спецификатор атрибута) |
Примечания
Наличие каждого отдельного атрибута на конкретной платформе можно проверить с помощью
__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(); // объявление f с четырьмя атрибутами [[gnu::always_inline, gnu::const, gnu::hot, nodiscard]] int f(); // то же самое, но использует один спецификатор атрибутов, содержащий четыре атрибута // C++17: [[using gnu : const, always_inline, hot]] [[nodiscard]] int f[[gnu::always_inline]](); // атрибут может появляться в нескольких спецификаторах int f() { return 0; } int main() {}
Отчеты о дефектах
Следующие отчеты об изменениях в поведении, являющиеся дефектными, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение в опубликованной версии | Корректное поведение |
|---|---|---|---|
| CWG 2079 | C++11 |
[[
не могло появляться внутри аргумента атрибута
|
разрешено |
| CWG 2538 | C++11 | было неясно, можно ли синтаксически игнорировать стандартные атрибуты | запрещено |
| CWG 2695 | C++11 | было неясно, можно ли семантически игнорировать стандартные атрибуты | запрещено |
| P2156R1 | C++11 | каждый стандартный атрибут должен был появляться не более одного раза в attribute-list | не требуется |
Смотрите также
__has_cpp_attribute
- проверяет наличие атрибута
|
|
|
C documentation
для
Attributes specifier sequence
|
Внешние ссылки
| 1. |
Атрибуты в GCC
. Эти атрибуты могут использоваться как
[[gnu::...]]
,
См. SO
.
|
| 2. | Атрибуты в Clang . |
| 3. | Атрибуты в MSVC . |