简体   繁体   English

折叠表达式中的短路

[英]Short circuiting in fold expressions

This is a self triggered question based on a self-answer I gave here .这是一个基于我在此处给出的自我回答的自我触发问题。

This seems a pretty convincing explanation of why short-circuiting of logical operators is available in fold expressions , and of the fact that wrapping a fold expression in a function with a variadic argument seems to be non short-circuting (in fact, the answer explains, it's the function call which triggers the evaluation of all arguments, before the short-circuit can take place inside the function body).似乎是一个非常令人信服的解释,解释了为什么折叠表达式中可以使用逻辑运算符的短路,并且使用可变参数将折叠表达式包装在 function 中似乎是非短路的(事实上,答案解释了,是 function 调用触发了对所有 arguments 的评估,在 function 主体内部发生短路之前)。

However, the following code seems to me, proves that (at least when the arguments in a fold expression are 2) the short-circuiting doesn't happen:但是,在我看来,以下代码证明(至少当折叠表达式中的 arguments 为 2 时)不会发生短路:

#include <assert.h>
#include <optional>

constexpr auto all_r = [](auto const& ... ps){
    return [&ps...](auto const& x){
        return (ps(x) && ...);
    };
};

constexpr auto all_l = [](auto const& ... ps){
    return [&ps...](auto const& x){
        return (... && ps(x));
    };
};

constexpr auto has_value = [](std::optional<int> o){
    return o.has_value();
};
constexpr auto has_positive = [](std::optional<int> o){
    assert(o.has_value());
    return o.value() > 0;
};

int main() {
    assert(!(has_value(std::optional<int>{}) && has_positive(std::optional<int>{})));
    //assert(!(has_positive(std::optional<int>{}) && has_value(std::optional<int>{}))); // expectedly fails at run-time


    assert(!all_r(has_value, has_positive)(std::optional<int>{}));
    assert(!all_l(has_value, has_positive)(std::optional<int>{})); // I expected this to fail at run-time
    //assert(!all_r(has_positive, has_value)(std::optional<int>{}));
    //assert(!all_l(has_positive, has_value)(std::optional<int>{})); // I expected this to succeed at run-time
}

... && ps(x) with four predicates a, b, c, d expands to ... && ps(x)有四个谓词a, b, c, d展开为

( ( a(x) && b(x) ) && c(x) ) && d(x)

which leads to this order of evaluation: ab c d这导致了这个评估顺序: ab c d

ps(x) &&... expands to ps(x) &&...展开为

a(x) && ( b(x) && ( c(x) && d(x) ) )

which leads to the same order of evaluation: ab c d这导致相同的评估顺序: ab c d

This does not change anything about short-circuiting;这不会改变任何关于短路的事情。 as soon as one is false, the evaluation stops.一旦一个是假的,评估就会停止。

Start with what Pack &&... means.Pack &&...的含义开始。

Cppreference has a pretty readable description. Cppreference有一个非常易读的描述。

Pack &&... becomes Pack1 && (Pack2 && (Pack3 && Pack4))) ... && Pack becomes (((Pack1 && Pack2) && Pack3) && Pack4 Pack &&...变成Pack1 && (Pack2 && (Pack3 && Pack4))) ... && Pack变成(((Pack1 && Pack2) && Pack3) && Pack4

When evaluating && we evaluate left to right at the top of the parse tree.在评估&&时,我们在解析树的顶部从左到右评估。

For the Pack&&... case, this top level && is Pack1 then the and operator, then (Pack2 && (Pack3 && Pack4)) .对于Pack&&...情况,这个顶级&&Pack1然后是 and 运算符,然后是(Pack2 && (Pack3 && Pack4)) && evaluates the left side first, and if false it stops. &&首先评估左侧,如果为假则停止。

For the ...&&Pack case, the top level && is way on the right.对于...&&Pack案例,顶层&&位于右侧。 Its left hand is (((Pack1 && Pack2) && Pack3) and its right hand is Pack4 .它的左手是(((Pack1 && Pack2) && Pack3) ,右手是Pack4

But to find out if the left hand is true, we keep on applying that rule.但是要确定左手是否为真,我们继续应用该规则。 And the very first term we end up evaluating is... Pack1 .我们最终评估的第一个术语是... Pack1 Which if it is false, we don't bother evaluating the rest.如果它是假的,我们不会费心评估 rest。

While the shape of the tree is different, it doesn't matter as much as one might think.虽然树的形状不同,但它并不像人们想象的那么重要。

  +
 / \
A   +
   / \
  B   C

and

      +
     / \
    +   C
   / \
  A   B

when doing an in order traversal visit the nodes in the same order, and left / right fold just switch which of these two expression trees is generated.在进行顺序遍历时,以相同的顺序访问节点,左/右折叠只需切换生成这两个表达式树中的哪一个。

There are cases where the left/right fold matters, but && on things evaluating to bool isn't one of them.在某些情况下,左/右折叠很重要,但&&在评估为bool的事物上不是其中之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM