为什么[[假设]]不被评估但也可能被评估?

Jan*_*tke 6 c++ attributes language-lawyer c++23 assumption

cppreference页面[[assume]]说:

[[assume( expression )]] 
Run Code Online (Sandbox Code Playgroud)

[...] 表达式没有被求值(但它仍然可能被求值)。

这个措辞让我很困惑。这里 cppreference 错了吗?如果不评估,为什么可能会评估?它不是像 中的表达式一样未计算的操作数吗sizeof?如果不可以,后果是什么?

Jan*_*tke 11

C++ 标准的说法几乎相同:

不计算表达式。[...]
[- 注 1:该表达式可能会被求值 ( [basic.def.odr] )。[...] - 尾注]

- [dcl.attr.假设]

至关重要的是,该标准规定该表达式不会被求值,但该表达式并不是一个未求值的操作数。措辞经过精心选择,非常重要。

表达式或转换可能会被求值,除非它是未求值的操作数 ( [expr.context] )、其子表达式或者此类上下文中的初始化或转换序列中的转换。

- [基本.def.odr]/3

结果

因此,[[assume]]不享有未评估操作数所拥有的任何特权。举一个例子,我们不能直接引用非静态数据成员:

struct S { int x; };

int main() {
    // OK, referring to non-static data members in decltype is possible,
    // because its expression is an unevaluated operand
    decltype(S::x) x;

    // ill-formed, illegal use of S::x in this context
    [[assume(S::x > 0)]];
}
Run Code Online (Sandbox Code Playgroud)

唯一有意义的[[assume]]潜在评估,因为它通知编译器,如果假设评估了某个运行时表达式true,则该表达式将评估为 。

该表达式必须是编译器可能评估的内容,即使它从未评估过。

  • 一个更好的例子(因为检查 `S::x > 0` 并没有多大意义)类似于 `auto f = [=]{ [[assume(x > 0)]]; 返回1;}` - 此处,必须捕获“x”。讨论的主要话题是 lambda 捕获案例。 (4认同)