Attribute specifier sequence (since C++11)
引入针对类型、对象、代码等的实现定义属性。
目录 |
语法
[[
属性列表
]]
|
(C++11 起) | ||||||||
[[
using
属性命名空间
:
属性列表
]]
|
(C++17 起) | ||||||||
其中
attribute-list
是由零个或多个
attribute
组成的逗号分隔序列(可能以省略号
...
结尾,表示
参数包展开
)
| 标识符 | (1) | ||||||||
属性命名空间
::
标识符
|
(2) | ||||||||
标识符
(
参数列表
(可选)
)
|
(3) | ||||||||
属性命名空间
::
标识符
(
参数列表
(可选)
)
|
(4) | ||||||||
其中 attribute-namespace 是一个 identifier ,而 argument-list 是一个括号、方括号和大括号保持平衡的符号序列( balanced-token-seq )。
|
若
[[using CC: opt(1), debug]] // 等价于 [[CC::opt(1), CC::debug]] [[using CC: CC::opt(1)]] // 错误:不能混合使用 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([[]])]]; // 正确 }
除了下列标准属性外,实现可能支持具有实现定义行为的任意非标准属性。 所有实现未知的属性都会被忽略,且不会引发错误。 (since C++17)
|
没有
属性命名空间
的属性,以及命名空间名为
|
(since C++20) |
标准属性
以下属性由 C++ 标准定义。
标准属性在语法上不可忽略:它们不能包含语法错误,必须应用于正确的目标对象,且参数中的实体必须满足 ODR使用 要求。
标准属性同样不能从语义上被忽略:若将所有特定标准属性的实例移除后产生的行为,本应是原始程序在包含该属性时符合规范的行为。
[[
noreturn
]]
(C++11)
|
指示函数不会返回
(属性说明符) |
[[
carries_dependency
]]
(C++11)
(removed in C++26)
|
指示 release-consume
std::memory_order
中的依赖链在函数内外传播
(属性说明符) |
[[
deprecated
]]
[[
deprecated
("
reason
")]]
(C++14)
(C++14)
|
指示允许使用带有此属性的名称或实体,但因某些
原因
不鼓励使用
(属性说明符) |
[[
fallthrough
]]
(C++17)
|
指示从前一个 case 标签的直落是故意的,不应被会对直落发出警告的编译器诊断
(属性说明符) |
[[
maybe_unused
]]
(C++17)
|
抑制编译器对未使用实体(如果有)的警告
(属性说明符) |
|
鼓励编译器在返回值被丢弃时发出警告
(属性说明符) |
|
|
指示编译器应针对通过语句的某条执行路径比其他任何执行路径更可能或更不可能的情况进行优化
(属性说明符) |
|
[[
no_unique_address
]]
(C++20)
|
指示非静态数据成员不需要具有与其类的所有其他非静态数据成员都不同的地址
(属性说明符) |
[[
assume
(
expression
)]]
(C++23)
|
指定
表达式
在给定点始终求值为
true
(属性说明符) |
[[
indeterminate
]]
(C++26)
|
指定对象如果未初始化则具有不确定值
(属性说明符) |
|
(TM TS)
|
指示应优化函数定义以从
synchronized 语句
调用
(属性说明符) |
注释
特定平台上每个独立属性的存在性可通过
__has_cpp_attribute
预处理器宏进行检测。
| 功能测试宏 | 值 | 标准 | 功能特性 |
|---|---|---|---|
__cpp_attributes
|
200809L
|
(C++11) | 属性 |
__cpp_namespace_attributes
|
201411L
|
(C++17) | 命名空间 的属性 |
示例
[[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() {}
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 应用于 | 发布时的行为 | 正确行为 |
|---|---|---|---|
| CWG 2079 | C++11 |
[[
不能出现在属性参数内部
|
允许 |
| CWG 2538 | C++11 | 未明确标准属性是否可在语法层面被忽略 | 禁止 |
| CWG 2695 | C++11 | 未明确标准属性是否可在语义层面被忽略 | 禁止 |
| P2156R1 | C++11 | 每个标准属性在 属性列表 中最多只能出现一次 | 非必需 |
参见
__has_cpp_attribute
- 检查属性是否存在
|
|
|
C 文档
关于
属性说明符序列
|
外部链接
| 1. |
GCC中的属性
。这些属性可作为
[[gnu::...]]
使用,
参见Stack Overflow
。
|
| 2. | Clang中的属性 。 |
| 3. | MSVC中的属性 。 |