如何解决在 `switch` 语句中正确使用 C++20 `[likely]]`/`[[unlikely]]`
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;
}
这无法在 clang 上编译!虽然这可能与 a compiler bug with [[fallthrough]]
有关,但它让我关注了标准。 relevant standard 具有以下示例(参见 §VII):
鼓励实现针对正在执行的案例进行优化(例如,以下代码中的值为 1):
switch (a) {
case 1: [[likely]]
foo();
break;
//...
}
所以。 . .它是哪个?顺便说一句,我希望标准是正确的,但这实际上是一个提案,而不是真正的标准 AFAICT——它可能已经改变了。而且,我希望文档至少在基本语法方面是正确的——除了它甚至无法编译。
解决方法
两个示例都是有效的,并且 Clang 出现了一个错误。 C++20 最新标准草案中的相关措辞是
[dcl.attr.likelihood]
1 属性标记 likely
和 unlikely
可应用于标签或语句。
语句和标记语句的相关语法产生式在适当位置具有属性说明符序列。
[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:
在
switch (a) {
case 1: [[likely]]
foo();
break;
//...
}
它适用于语句 foo();
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。