为类型、对象、代码等引入由实现定义的属性。
[[
attr]]
[[
attr1, attr2, attr3(
args)
]]
[[
namespace::
attr(
args)
]]
alignas-说明符
正式而言,语法是
[[ 属性列表 ]] | (C++11 起) | |
[[ using 属性命名空间 : 属性列表 ]] | (C++17 起) | |
其中 属性列表 是零或更多 属性 的逗号分隔列表(可选地以指示包展开的省略号 …
结束)
标识符 | ||
属性命名空间 :: 标识符 | ||
标识符 ( 实参列表 ) | ||
属性命名空间 :: 标识符 ( 实参列表 ) | ||
1) 简单属性,例如 [[noreturn]]
2) 有命名空间的属性,例如 [[gnu::unused]]
3) 有实参的属性,例如 [[deprecated("because")]]
4) 既有命名空间又有实参列表的属性
若 using: namespace 出现在属性列表开端,则属性列表中无其他属性可以指定命名空间:由 using 所指定的命名空间应用到它们全部:
| (C++17 起) |
解释
属性为各种由实现定义的语言扩展(例如 GNU 与 IBM 的语言扩展 attribute((…))
,微软的语言扩展 __declspec()
等)提供了统一化的语法。
属性可用在 C++ 程序中的几乎所有位置,而且可应用于几乎所有事物:类型、变量、函数、名字、代码块、整个翻译单元,不过每个特定的属性都仅在实现所容许之处有效:[[expect_true]]
可能是只能与 if,而非与类声明一同使用的属性,[[omp::parallel()]]
可能是应用到代码块或 for 循环,而非到类型 int
等的属性。(请注意这两个属性只是虚构的例子,有关标准与一些非标准属性,见下文)
在声明中,属性可出现在整个声明之前,或直接跟在被声明实体的名字之后,这些情况下它们被组合起来。大多数其他情形中,属性应用于直接位于其之前的实体。
虽然 alignas
说明符拥有不同的语法,但它是属性序列说明符的一部分。它可出现于 [[…]]
属性出现处,并可与它们混合(假定用于容许 alignas 之处)
两个连续的方括号记号([[
)只能出现于引入属性说明符之处,或在属性实参之内。
- void f() {
- int y[3];
- y[[] { return 0; }()] = 1; // 错误
- int i [[cats::meow([[]])]]; // OK
- }
除了以下所列出的标准属性之外,实现还可能支持任意拥有由实现定义的行为的非标准属性。所有实现所未知的属性均被忽略,且不产生错误。 (C++17 起)
标准属性
C++ 标准仅定义下列属性。
示例
运行此代码
- [[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() {}