Overview

Attribute specifier sequence(Since C++11)的引入是为了指定type, object, code等实现定义的属性。
     [[attr]] [[attr1, attr2, attr3(arg)]] [[namespace::attr(arg)]] alignas_specifier
形式化地,语法应该如下:

[[ attribute-list ]] (Since C++11)
[[ using attribute-namespace:attribute-list ]] (Since C++17)
attribute-list应该为以”,“分隔的零个或多个属性序列(可以以”…“(ellipsis))结尾,表示pack expansion)
identifier (1)
attribute-namespace::attribute-list (2)
identifier (attribute-list) (3)
attribute-namespace::identifier(argument-list) (4)

1) 简单的属性,比如 [[noreturn]]

2) 带命名空间的属性:比如 [[gnu::unused]]

3) 带参数的属性:比如 [[deprecated("because")]]

如果using:namespace出现在attribute-list的开头,那么attribute-list中其他属性将不能指定namespace(命名空间),并且using:namespace将会应用到attribute-list的其他属性
[[using CC:opt(1), debug]] //和[[CC:opt(1), CC:debug]]相同
[[using CC: CC::opt(1)]] //错误:不能结合 using和scoped属性
(Since C++17)

Explanation

Attributes提供了统一的实现定义的语言扩展。比如GNU和IBM提供的语言拓展attribute((…)),Mircosoft extension __declspec()等。 属性能用于C++程序的几乎任何地方.并且几乎能应用于每个地方:类型,变量,函数,名字,代码块,全部的翻译单元,尽管每个特别的属性只在实现允许的情形下有效: [[expect_true]] 属性只能应用于 if ,而不能用于类声明, [[omp::parallel]] 能够应用于code block(代码块)或者 for loop,而不能应用于type int等.(注意这两个属性是虚构的例子,关于更多standard 或 non-standard attributes,请查看下面更多细节)。 在declaration(声明)中,属性可能同时出现在整个声明的前面和声明实体名字的后面,这种情况下,它们将结合,在大多数其他情境下,属性直接应用于在前的实体。 alignas specifierattribute specifier seq的一部分,它可能出现在 [[...]] 属性出现的地方,并且可能与它们混合(只要在允许使用 alignas 的地方使用)。

两个连续的方括号([[)可能只出现在引进一个 attribute-specifier 或者在 attribute-argument 内部中.

void f()
{
    int y[3];
    y[[ ] { return 0; }()] = 1; // error
    int i [[ cats::meow([[]])]]; // OK
}
此外,standard attributes(标准属性)如下表所列,这些属性可能支持任意的良好定义行为的non-standard attributes(非标准属性).
任意对于实现未知的属性将被忽略,而不会造成错误.(Since C++17)

Standard Attributes

只有如下的属性被C++ standard定义

表明前一条case标签没有break是故意的,编译器不应该把fall-through诊断为警告
[[noreturn]](Since C++11) 表明该函数不会返回
[[carries_dependency]](Since C++11) 表明在release-consumestd::memory_order下可以传播进和出函数
[[deprecated]](Since C++14)
[[deprecated("reason")]](Since C++14)
表明该名称的使用或者实体的声明是被允许的,但是由于某些reason不推荐使用
[[fallthrough]](Since C++17)
[[nodiscard(Since C++17)
[[nodiscard("reason")]](Since C++20)
鼓励编译器发出警告,如果返回值被废弃
[[maybe_unused]](Since C++17) 禁止编译器对任何未使用的实体发出警告(如果有)
[[likely]](Since C++20)
[[unlikely]](Since C++20)
表明编译器应该优化执行某种情况下的路径更可能/不可能多于其他路径
[[no_unique_address]] 表明non-static data member不必需要一个地址来和该类其他 non-static data member区分
[[optimize_for_synchronized]] 表明函数定义不应该被synchronized statement调用优化(Since C++20)