attributes(属性)

属性说明符序列(C++11 起)

为类型、对象、代码等引入由实现定义的属性。

[[属性]] [[属性1, 属性2, 属性3(实参)]] [[命名空间::属性(实参)]] alignas说明符

正式而言,语法是 [[ 属性列表 ]]

其中 属性列表 是由逗号分隔的零或更多个 属性 的序列(可以以指示包展开的省略号 … 结束)
标识符
属性命名空间 :: 标识符
标识符 (实参列表)
属性命名空间 :: 标识符 (实参列表)

  1. 简单属性,例如 [[noreturn]]
  2. 有命名空间的属性,例如 [[gnu::unused]]
  3. 有实参的属性,例如 [[deprecated("because")]]
  4. 既有命名空间又有实参列表的属性

属性为各种由实现定义的语言扩展(例如 GNU 与 IBM 的语言扩展 __attribute__((...)),微软的语言扩展 __declspec() 等)提供了统一化的语法。

属性可用在 C++ 程序中的几乎所有位置,而且可应用于几乎所有事物:类型、变量、函数、名字、代码块、整个翻译单元,不过每个特定的属性都只在实现允许范围内有效:[[expect_true]] 可能是只能与 if,而非与类声明一同使用的属性,[[omp::parallel()]] 可能是应用到代码块或 for 循环,而非到类型 int 等的属性。(请注意以上两个属性只是虚构的例子,有关标准与一些非标准属性请见下文)

在声明中,属性既可以在整个声明之前出现,也可以直接跟在被声明实体的名字之后,这些情况下它们被组合起来。大多数其他情形中,属性应用于直接位于其之前的实体。

虽然 alignas 说明符拥有不同的语法,但它是属性序列说明符的一部分。它可以在 … 属性出现的地方出现,并可以和它们混合(假设此处允许使用 alignas)

两个连续的方括号记号([[)只能在引入属性说明符的地方出现,或在属性实参之内。

1
2
3
4
5
6
void f()
{
int y[3];
y[[] { return 0; }()] = 1; // 错误
int i [[cats::meow([[]])]]; // OK
}

除了以下所列出的标准属性之外,实现还可能支持任意拥有由实现定义的行为的非标准属性。所有实现所未知的属性均被忽略,且不产生错误。 (C++17 起)

无 属性命名空间 的属性与名字以 std 或 std 后随一或多个数字的 属性命名空间 为未来标准化保留。即每个非标准属性都在实现提供的 属性命名空间 中,例如 [[gnu::may_alias]]、 [[clang::trivial_abi]] 和 [[msvc::noop_dtor]]。(C++20 起)
标准属性

C++ 标准仅定义下列属性。
[[noreturn]](C++11 起) 指示函数不返回
[[carries_dependency]](C++11 起) 指示释放消费 std::memory_order 中的依赖链传入和传出该函数。
[[deprecated]](C++14 起)
[[deprecated(“原因”)]](C++14 起) 指示允许使用声明有此属性的名称或实体,但因 原因 而不鼓励使用。
[[fallthrough]](C++17 起) 指示从前一 case 标号直落是有意的,而在发生直落时给出警告的编译器不应该为此诊断。
[[nodiscard]](C++17 起)
[[nodiscard(“原因”)]](C++20 起) 鼓励编译器在返回值被舍弃时发布警告。
[[maybe_unused]](C++17 起) 压制编译器在未使用实体上的警告,若存在。
[[likely]](C++20 起)
[[unlikely]](C++20 起) 指示编译器应该针对通过某语句的执行路径比任何其他执行路径更可能或更不可能的情况进行优化。
[[no_unique_address]](C++20 起) 指示非静态数据成员不需要拥有不同于其类的所有其他非静态数据成员的地址。
[[optimize_for_synchronized]](TM TS) 指示应该针对来自 synchronized 语句的调用来优化该函数定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 示例
[[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() {}