attribute specifier sequence(since C++11)

< cpp‎ | language

Introduces implementation-defined attributes for types, objects, code, etc.

[[attr]] [[attr1, attr2, attr3(args)]] [[namespace::attr(args)]] alignas_specifier

Formally, the syntax is

[[ attribute-list ]] (since C++11)
[[ using attribute-namespace : attribute-list ]] (since C++17)
[[ contract-attribute-token contract-level(optional) identifier(optional) : expression ]] (since C++20)

where attribute-list is a comma-separated sequence of zero or more attributes (possibly ending with an ellipsis ... indicating a pack expansion)

attribute-namespace :: identifier
identifier ( argument-list )
attribute-namespace :: identifier ( argument-list )
1) simple attribute, such as [[noreturn]]
2) attribute with a namespace, such as [[gnu::unused]]
3) attribute with arguments, such as [[deprecated("because")]]
4) attribute with both a namespace and an argument list

If using: namespace appears in the beginning of an attribute list, no other attributes in the attribute list can specify a namespace: the namespace specified in a using applies to them all:

[[using CC: opt(1), debug]] // same as [[CC::opt(1), CC::debug]]
[[using CC: CC::opt(1)]] // error: cannot combine using and scoped attribute
(since C++17)

The contract attributes use a special attribute syntax. Each contract attribute must be in its own attribute specifier ([[]]). Multiple contract attribute specifiers can be applied to the same entity.

(since C++20)


Attributes provide the unified standard syntax for implementation-defined language extensions, such as the GNU and IBM language extensions __attribute__((...)), Microsoft extension __declspec(), etc.

An attribute can be used almost everywhere in the C++ program, and can be applied to almost everything: to types, to variables, to functions, to names, to code blocks, to entire translation units, although each particular attribute is only valid where it is permitted by the implementation: [[expect_true]] could be an attribute that can only be used with an if, and not with a class declaration. [[omp::parallel()]] could be an attribute that applies to a code block or to a for loop, but not to the type int, etc. (note these two attributes are fictional examples, see below for the standard and some non-standard attributes)

In declarations, attributes may appear both before the whole declaration and directly after the name of the entity that is declared, in which case they are combined. In most other situations, attributes apply to the directly preceding entity.

The alignas specifier is a part of the attribute specifier sequence, although it has different syntax. It may appear where the [[...]] attributes appear and may mix with them (provided it is used where alignas is permitted)

Two consecutive left square bracket tokens ([[) may only appear when introducing an attribute-specifier or inside an attribute argument.

void f() {
  int y[3];
  y[[] { return 0; }()] = 1;    // error
  int i [[cats::meow([[]])]]; // OK

Besides the standard attributes listed below, implementations may support arbitrary non-standard attributes with implementation-defined behavior. All attributes unknown to an implementation are ignored without causing an error. (since C++17)

Standard attributes

Only the following attributes are defined by the C++ standard.

[[noreturn]] indicates that the function does not return
[[carries_dependency]] indicates that dependency chain in release-consume std::memory_order propagates in and out of the function
indicates that the use of the name or entity declared with this attribute is allowed, but discouraged for some reason
[[fallthrough]](C++17) indicates that the fall through from the previous case label is intentional and should not be diagnosed by a compiler that warns on fall-through
[[nodiscard]](C++17) encourages the compiler to issue a warning if the return value is discarded
[[maybe_unused]](C++17) suppresses compiler warnings on unused entities, if any
indicates that the compiler should optimize for the case where a path of execution through a statement is more or less likely than any other path of execution
[[no_unique_address]](C++20) indicates that a non-static data member need not have an address distinct from all other non-static data members of its class
specifies preconditions, postconditions, and assertions for functions
[[optimize_for_synchronized]](TM TS) indicates that the function definition should be optimized for invocation from a synchronized statement


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

External links

C++ attributes supported by Clang