Spec-Zone.ru › C++

Последовательность спецификаторов атрибутов(с C++11)

Вводит определённые реализацией атрибуты для типов, объектов, кода и т.д.

Синтаксис

[[ список_атрибутов ]] (с C++11)
[[ using пространство_имён_атрибутов : список_атрибутов ]] (с C++17)

где список_атрибутов — это список из нуля или более атрибутов, разделённых запятыми (возможно, с многоточием ... указывающим на развёртывание пакета параметров).

идентификатор (1)
пространство_имён_атрибутов :: идентификатор (2)
идентификатор ( список_аргументов (необязательно) ) (3)
пространство_имён_атрибутов :: идентификатор ( список_аргументов (необязательно) ) (4)

где пространство_имён_атрибутов — это идентификатор, а список_аргументов — это последовательность токенов, где скобки, квадратные скобки и фигурные скобки сбалансированы (сбалансированная_последовательность_токенов).

1) Простой атрибут, такой как [[noreturn]].
2) Атрибут с именем пространства имён, например [[gnu::unused]].
3) Атрибут с аргументами, например [[deprecated("because")]].
4) Атрибут с именем пространства имён и списком аргументов.

Если using namespace: появляется в начале списка атрибутов, другие атрибуты в списке не могут указывать пространство имён: пространство имён, указанное в using, применяется ко всем им:

[[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)

Атрибут без пространство_имён_атрибутов и пространство_имён_атрибутов, имя которого — std или std, за которым следуют один или более цифр, зарезервировано для будущей стандартизации. То есть, каждый нестандартный атрибут находится в пространстве_имён_атрибутов, предоставляемом реализацией, например, [[gnu::may_alias]], [[clang::trivial_abi]], и [[msvc::noop_dtor]].

(с 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API