Namespaces
Variants

Attribute specifier sequence (since C++11)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

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

Содержание

Синтаксис

[[ список-атрибутов ]] (начиная с 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 ).

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 specifier является частью последовательности спецификаторов атрибутов, хотя имеет другой синтаксис. Он может появляться там, где появляются атрибуты [[...]] и может смешиваться с ними (при условии, что он используется там, где alignas разрешён).

Два последовательных токена левой квадратной скобки ( [[ ) могут появляться только при введении спецификатора атрибута или внутри аргумента атрибута.

void f()
{
    int y[3];
    y[[] { return 0; }()] = 1;  // ошибка
    int i [[cats::meow([[]])]]; // OK
}

Помимо стандартных атрибутов, перечисленных ниже, реализации могут поддерживать произвольные нестандартные атрибуты с поведением, определяемым реализацией. Все атрибуты, неизвестные реализации, игнорируются без выдачи ошибки. (начиная с C++17)

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

(since C++20)

Стандартные атрибуты

Следующие атрибуты определены стандартом C++.

Стандартные атрибуты не могут быть синтаксически проигнорированы: они не могут содержать синтаксических ошибок, должны применяться к корректной цели, и сущности в аргументах должны быть ODR-use .

Стандартные атрибуты также не могут быть семантически проигнорированы: поведение со всеми экземплярами конкретного стандартного атрибута удаленными должно было бы быть соответствующим поведению для исходной программы с присутствующим атрибутом.

(C++11)
указывает, что функция не возвращает управление
(спецификатор атрибута)
(C++11) (удален в C++26)
указывает, что цепочка зависимостей в release-consume std::memory_order распространяется внутрь и наружу функции
(спецификатор атрибута)
[[ deprecated ]] [[ deprecated (" reason ")]]
(C++14) (C++14)
указывает, что использование имени или сущности, объявленной с этим атрибутом, разрешено, но не рекомендуется по некоторой причине
(спецификатор атрибута)
(C++17)
указывает, что переход на следующую метку case является преднамеренным и не должен диагностироваться компилятором, который предупреждает о таких переходах
(спецификатор атрибута)
(C++17)
подавляет предупреждения компилятора о неиспользуемых сущностях, если таковые имеются
(спецификатор атрибута)
[[ nodiscard ]] [[ nodiscard (" reason ")]]
(C++17) (C++20)
побуждает компилятор выдавать предупреждение, если возвращаемое значение игнорируется
(спецификатор атрибута)
(C++20) (C++20)
указывает, что компилятор должен оптимизировать случай, когда путь выполнения через оператор более или менее вероятен, чем любой другой путь выполнения
(спецификатор атрибута)
(C++20)
указывает, что нестатический член данных не обязан иметь адрес, отличный от всех других нестатических членов данных своего класса
(спецификатор атрибута)
[[ assume ( expression )]]
(C++23)
указывает, что выражение всегда будет вычисляться в true в данной точке
(спецификатор атрибута)
(C++26)
указывает, что объект имеет неопределенное значение, если он не инициализирован
(спецификатор атрибута)
указывает, что определение функции должно быть оптимизировано для вызова из 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 .