【问题标题】:Are fold expressions subject to short-circuiting?折叠表达式是否会短路?
【发布时间】:2018-05-01 04:15:18
【问题描述】:

在 C++17 中,当使用 &&|| 作为其运算符时,折叠表达式是否受 short-circuiting 约束?如果是这样,这是在哪里指定的?

【问题讨论】:

标签: c++ c++17 fold short-circuiting


【解决方案1】:

是的,使用 &&|| 操作符的折叠表达式可能会短路,但通常需要注意的是,它发生在内置含义上,但不适用于重载的操作符函数。

折叠表达式的含义在[temp.variadic]/9中定义:

折叠表达式的实例化产生:

  • ((E_1 op E_2) op ...) op E_N 用于一元左折叠,

  • E_1 op (... op (E_N_minus_1 op E_N)) 用于一元右折叠,

  • (((E op E_1) op E_2) op ...) op E_N 用于二进制左折叠,并且

  • E_1 op (... op (E_N_minus_1 op (E_N op E))) 用于二进制右折叠。

在每种情况下,op 都是 fold-operator,....

由于折叠表达式的实例化是根据包含运算符的表达式,因此适用于运算符的所有常规规则,包括重载决策、评估顺序和内置运算符时的短路。

【讨论】:

    【解决方案2】:

    虽然@aschepler 的answer 是特别正确的,但我想重复一下我在shared regarding another fine technical point (tuple order of destruction) 上的人生教训:

    如果您可以针对多种备选方案制定合理的论据,说明为什么该备选方案应该是标准规定的备选方案 - 那么您不应该假设其中任何一个是强制性的(即使其中一个恰好是)。

    在折叠表达式和短路逻辑的上下文中 - 阅读可变参数模板代码已经足够困难了,所以我会尝试让我的代码的读者不知道折叠短路是否发生。 ..

    如果你无法避免写 andor 折叠,至少要慷慨地评论短路行为。

    【讨论】:

    • 恕我直言,这不适用于此处。对于std::tuple,完全未指定如何存储元组元素(它们是元组的数据成员吗?元组的一个或多个基类的数据成员?元组的一些其他数据成员的数据成员?使用放置创建 - unsigned char?!) 的无类型缓冲区中的新内容。所以你不能对初始化的顺序做出任何结论。对于折叠表达式,标准指定了扩展表达式的精确形式,因此适用相关运算符的通常语义。
    • @JonathanWakely:我能理解你为什么要区分这两种情况。但是,标准可能有其他说法,例如“短路是与 C 兼容的遗留特性,这就是它从不适用于重载运算符的原因;而且由于 fold 不是 C-ish 代码,我们不需要支持短路怪癖。”这可能不是最终发生的事情,但这并不完全荒谬。即使是重载与非重载的短路行为也已经足够令人困惑了。
    • 它不适用于重载运算符的原因与丢弃遗留的 C-ish 内容无关。我知道你从哪里来,但幸运的是 C++ 没有做出这样的选择:折叠表达式中的运算符与折叠表达式之外的运算符具有相同的含义。另一种选择是可怕的恕我直言。
    • @JonathanWakely:我并不是反对标准委员会的决定。我只是说这是唯一可以想象的决定还不够明显,因此在编写代码时最好不要依赖读者知道决定是什么。
    • 而且我认为最好依靠语言标准实际保证的内容,而不仅仅是您无法想象以任何其他方式定义的内容。如果你总是遵循“我可以想象它的工作方式不同,所以我会假设这可能是真的”,那么你就会受制于你的想象力有多有创造力(以及其他人的想象力有多缺乏创造力!)和“甚至如果其中一个碰巧是“建议积极忽略标准所保证的内容。我认为您的建议是有意义的,但并不是一个好的经验法则。
    猜你喜欢
    • 2021-05-13
    • 1970-01-01
    • 1970-01-01
    • 2017-08-20
    • 2020-01-25
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多