在 `switch` 语句中正确使用 C++20 `[likely]]`/`[[unlikely]]`
Correctly using C++20 `[likely]]`/`[[unlikely]]` in `switch` statements
C++20 有方便的 [[likely]]
/[[unlikely]]
属性来指导代码生成。例如,您可以指定一个分支可能被采用:
if (b) [[likely]] { /*...*/ }
同样,可以在 switch
语句中使用这些属性。 . .不知何故? The documentation 建议使用以下示例(格式略有不同):
switch (i) {
case 1:
[[fallthrough]];
[[likely]] case 2:
return 1;
}
其含义显然是 [[likely]]
/[[unlikely]]
在 case
语句之前。互联网似乎几乎普遍传播这种用法。
但是,请考虑以下类似代码(我所做的只是将 [[likely]]
移动到另一个 case
):
switch (i) {
[[likely]] case 1:
[[fallthrough]];
case 2:
return 1;
}
编译失败!虽然这可能与 a compiler bug with [[fallthrough]]
, it got me looking at the standards. The relevant standard 有关,但有以下示例(参见 §VII):
implementations are encouraged to optimize for that case being executed (eg. a having the value 1 in the following code):
switch (a) {
case 1: [[likely]]
foo();
break;
//...
}
也就是说,属性出现在 之后 大小写标签,而不是之前。
所以。 . .是哪一个?顺便说一句,我希望该标准是正确的,但这实际上是一个提案,而不是真正的标准 AFAICT — 从那以后它可能会被更改。而且,我希望文档(如果没有别的)至少在基本语法方面是正确的——除了它甚至不能编译。
两个例子都有效,Clang 出现了一个错误。 C++20 最新标准草案中的相关措辞是
[dcl.attr.likelihood]
1 The attribute-tokens likely
and unlikely
may be applied to labels or statements.
语句和标记语句的相关语法产生式在适当的位置具有属性说明符序列。
[stmt.pre]
statement:
labeled-statement
attribute-specifier-seq expression-statement
attribute-specifier-seq compound-statement
attribute-specifier-seq selection-statement
attribute-specifier-seq iteration-statement
attribute-specifier-seq jump-statement
declaration-statement
attribute-specifier-seq try-block
[stmt.label]
labeled-statement:
attribute-specifier-seq identifier : statement
attribute-specifier-seq case constant-expression : statement
attribute-specifier-seq default : statement
在
switch (i) {
case 1:
[[fallthrough]];
[[likely]] case 2:
return 1;
}
该属性适用于 case 2:
wheras in
switch (a) {
case 1: [[likely]]
foo();
break;
//...
}
它适用于语句foo();
。
C++20 有方便的 [[likely]]
/[[unlikely]]
属性来指导代码生成。例如,您可以指定一个分支可能被采用:
if (b) [[likely]] { /*...*/ }
同样,可以在 switch
语句中使用这些属性。 . .不知何故? The documentation 建议使用以下示例(格式略有不同):
switch (i) {
case 1:
[[fallthrough]];
[[likely]] case 2:
return 1;
}
其含义显然是 [[likely]]
/[[unlikely]]
在 case
语句之前。互联网似乎几乎普遍传播这种用法。
但是,请考虑以下类似代码(我所做的只是将 [[likely]]
移动到另一个 case
):
switch (i) {
[[likely]] case 1:
[[fallthrough]];
case 2:
return 1;
}
编译失败!虽然这可能与 a compiler bug with [[fallthrough]]
, it got me looking at the standards. The relevant standard 有关,但有以下示例(参见 §VII):
implementations are encouraged to optimize for that case being executed (eg. a having the value 1 in the following code):
switch (a) {
case 1: [[likely]]
foo();
break;
//...
}
也就是说,属性出现在 之后 大小写标签,而不是之前。
所以。 . .是哪一个?顺便说一句,我希望该标准是正确的,但这实际上是一个提案,而不是真正的标准 AFAICT — 从那以后它可能会被更改。而且,我希望文档(如果没有别的)至少在基本语法方面是正确的——除了它甚至不能编译。
两个例子都有效,Clang 出现了一个错误。 C++20 最新标准草案中的相关措辞是
[dcl.attr.likelihood]
1 The attribute-tokens
likely
andunlikely
may be applied to labels or statements.
语句和标记语句的相关语法产生式在适当的位置具有属性说明符序列。
[stmt.pre]
statement: labeled-statement attribute-specifier-seq expression-statement attribute-specifier-seq compound-statement attribute-specifier-seq selection-statement attribute-specifier-seq iteration-statement attribute-specifier-seq jump-statement declaration-statement attribute-specifier-seq try-block
[stmt.label]
labeled-statement: attribute-specifier-seq identifier : statement attribute-specifier-seq case constant-expression : statement attribute-specifier-seq default : statement
在
switch (i) {
case 1:
[[fallthrough]];
[[likely]] case 2:
return 1;
}
该属性适用于 case 2:
wheras in
switch (a) {
case 1: [[likely]]
foo();
break;
//...
}
它适用于语句foo();
。