Атрибуты определяют дополнительную информацию для различных исходных конструкций, таких как типы, переменные, имена, блоки или единицы перевода.
attribute-specifier-seq: attribute-specifier-seqopt attribute-specifier
attribute-specifier: [ [ attribute-using-prefixopt attribute-list ] ] alignment-specifier
alignment-specifier: alignas ( type-id ...opt ) alignas ( constant-expression ...opt )
attribute-using-prefix: using attribute-namespace :
attribute-list: attributeopt attribute-list , attributeopt attribute ... attribute-list , attribute ...
attribute: attribute-token attribute-argument-clauseopt
attribute-token: identifier attribute-scoped-token
attribute-scoped-token: attribute-namespace :: identifier
attribute-namespace: identifier
attribute-argument-clause: ( balanced-token-seqopt )
balanced-token-seq: balanced-token balanced-token-seq balanced-token
balanced-token: ( balanced-token-seqopt ) [ balanced-token-seqopt ] { balanced-token-seqopt } any token other than a parenthesis, a bracket, or a brace
Если an attribute-specifier содержит attribute-using-prefix, attribute-listследующее, которое attribute-using-prefix не должно содержать, attribute-scoped-token и каждый attribute-tokenв, который attribute-list обрабатывается так, как если бы его identifierпрефикс былN::, гдеN - это attribute-namespace указанное в attribute-using-prefix. [ Note: Это правило не накладывает ограничений на то, как объект attribute-using-prefix влияет на токены в attribute-argument-clause. ] [ — end note Example:
[[using CC: opt(1), debug]] // same as [[CC::opt(1), CC::debug]] void f() {} [[using CC: opt(1)]] [[CC::debug]] // same as [[CC::opt(1)]] [[CC::debug]] void g() {} [[using CC: CC::opt(1)]] // error: cannot combine using and scoped attribute token void h() {}
— end example ]
В attribute-listобъекте многоточие может отображаться только в том случае, если это attributeразрешено спецификацией. attributeС последующим многоточием являетсяpack expansion. Не , attribute-specifierчто не содержит attributes не имеет никакого эффекта. Порядок, в котором attribute-tokens появляются символы attribute-list, не имеет значения. Если a keyword или an,alternative token которое удовлетворяет синтаксическим требованиям identifier, содержится в an attribute-token, это считается идентификатором. Нет name lookup не выполняется ни с одним из идентификаторов, содержащихся в файле attribute-token. attribute-tokenОпределяет дополнительные требования к attribute-argument-clause(если таковые имеются).
Каждый из них attribute-specifier-seqотноситсяappertain к некоторому объекту или утверждению, идентифицированному синтаксическим контекстом, в котором он встречается (пункт[stmt.stmt], пункт[dcl.dcl], пункт[dcl.decl]). Если attribute-specifier-seqэлемент, принадлежащий какой-либо сущности или оператору, содержит элемент attributeили, alignment-specifierкоторый не может применяться к этой сущности или оператору, программа сформирована неправильно. Если a attribute-specifier-seq принадлежит afriend declaration, это объявление должно быть определением. Нет attribute-specifier-seqне относится к explicit instantiation.
Для attribute-token (включая attribute-scoped-token), не указанного в этом международном стандарте, поведение определяется реализацией. Все, attribute-tokenчто не распознается реализацией, игнорируется. [ Note: Каждая реализация должна выбрать отличительное имя для attribute-namespaceфайла attribute-scoped-token. ] — end note
Два последовательные левые квадратные маркеры скобки должны появляться только тогда , когда внедрив attribute-specifierили в пределах balanced-token-seqот attribute-argument-clause. [ Note: Если две последовательные левые квадратные скобки появляются там, где attribute-specifierнедопустимо, программа имеет неправильный формат, даже если скобки соответствуют альтернативной грамматической постановке. ] [ — end note Example:
int p[10]; void f() { int x = 42, y[5]; int(p[[x] { return x; }()]); // error: invalid attribute on a nested declarator-id and // not a function-style cast of an element of p. y[[] { return 2; }()] = 2; // error even though attributes are not allowed in this context. int i [[vendor::attr([[]])]]; // well-formed implementation-defined attribute. }
— end example ]