在`switch`语句中正确使用C++20的`[likely]`/`[[unlikely]]`关键字

7

C++20提供了方便的[[likely]]/[[unlikely]]属性来指导代码生成。例如,您可以通过以下方式指定分支很可能被执行:

if (b) [[likely]] { /*...*/ }

同样,我们可以在 switch 语句中使用这些属性……但怎么使用呢?文档 给出了下面的示例(已稍作格式化):

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上编译失败了!尽管这可能与具有[[fallthrough]]的编译器错误有关,但这让我开始研究标准。 相关标准附带了以下示例(请参见§VII):

鼓励实现为执行该情况进行优化(例如,在以下代码中a具有值1):

switch (a) {
    case 1: [[likely]]
        foo();
        break;
    //...
}

也就是说,属性在案例标签之后,而不是之前。

那么...到底是哪个呢?一开始,我期望标准是正确的,但那只是一个提议,不是真正的标准(据我所知,它可能已经被改变)。而且,我至少期望文档对基本语法是正确的——但它甚至无法编译。

1个回答

4
两个示例都是有效的,而Clang正在展示一个错误。C++20最新标准草案中相关措辞如下:
[dcl.attr.likelihood] 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();

虽然简洁很好,但我觉得语言语法规则在这里非常重要。此外,我很难看出 [[likely]] 应用于 foo(); 和应用于 case 语句之间的区别,因为(除了 fallthrough 或 goto 之外),case 语句是唯一可以到达 foo(); 的方式。当然,我可以看到 [[likely]] foo(); 作为一个孤立的结构工作,但论文确实说这会影响 case - geometrian
@imallett - 它它应该影响情况(但不是转到标签),但那里提出的规范措辞只涉及语句。此外,该提案也没有涉及所需的语法更改。标准包含更精细的措辞。您看不到任何区别,因为没有区别。规范措辞的设计只是为了允许更灵活的放置。 - StoryTeller - Unslander Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接