C++ 折叠表达式中的短路
这是一个自我触发的问题,基于我给出的自我回答 这似乎是一个非常令人信服的解释,解释了为什么在中可以使用逻辑运算符的短路,以及在函数中使用可变参数包装折叠表达式似乎是非短路的事实(事实上,答案解释说,是函数调用触发了对所有参数的求值,然后函数体内部才会发生短路) 然而,在我看来,以下代码证明(至少当折叠表达式中的参数为2时)不会发生短路:C++ 折叠表达式中的短路,c++,c++17,lazy-evaluation,short-circuiting,fold-expression,C++,C++17,Lazy Evaluation,Short Circuiting,Fold Expression,这是一个自我触发的问题,基于我给出的自我回答 这似乎是一个非常令人信服的解释,解释了为什么在中可以使用逻辑运算符的短路,以及在函数中使用可变参数包装折叠表达式似乎是非短路的事实(事实上,答案解释说,是函数调用触发了对所有参数的求值,然后函数体内部才会发生短路) 然而,在我看来,以下代码证明(至少当折叠表达式中的参数为2时)不会发生短路: #包括 #包括 constexpr auto all_r=[](auto const&…ps){ 返回[&ps..](自动常量和x){ 回报率(ps(x)&…)
#包括
#包括
constexpr auto all_r=[](auto const&…ps){
返回[&ps..](自动常量和x){
回报率(ps(x)&…);
};
};
constexpr auto all_l=[](auto const&…ps){
返回[&ps..](自动常量和x){
回报率(…&&ps(x));
};
};
constexpr auto具有_值=[](标准::可选o){
返回o.具有_值();
};
constexpr auto具有_正=[](标准::可选o){
断言(o.has_value());
返回o.value()>0;
};
int main(){
断言(!(has_值(std::optional{})和&has_正值(std::optional{}));
//assert(!(has_positive(std::optional{})和&has_value(std::optional{}));//在运行时预期失败
assert(!all_r(has_value,has_positive)(std::optional{}));
assert(!all_l(has_value,has_positive)(std::optional{});//我希望它在运行时失败
//assert(!all_r(has_正值,has_值)(std::optional{}));
//assert(!all_l(has_-positive,has_-value)(std::optional{});//我希望这在运行时能够成功
}
从Pack&&…
的含义开始
有一个相当可读的描述
Pack&…
变成Pack1&&(Pack2&&(Pack3&&Pack4))
…&&包装
变为((包装1和包装2)和包装3)和包装4
在计算&&
时,我们在解析树的顶部从左到右进行计算
对于Pack&&…
案例,此顶级&&
是Pack1
然后是and运算符,然后是(Pack2&&(Pack3&&Pack4))
首先计算左侧,如果为false,则停止
对于..&&Pack
案例,顶层&
位于右侧。它的左手是((Pack1&&Pack2)和&Pack3)
,右手是Pack4
但是为了找出左手是否为真,我们继续应用这个规则。我们最后计算的第一个术语是…Pack1
。如果它为假,我们就不去计算其余的
虽然树的形状不同,但它没有人们想象的那么重要
+
/ \
A +
/ \
B C
及
执行顺序遍历时,以相同的顺序访问节点,左/右折叠只需切换生成这两个表达式树中的哪一个
在某些情况下,左/右折叠很重要,但对事物求值为bool的&
不在其中。..&&ps(x)
带有四个谓词a、b、c、d
扩展为
( ( a(x) && b(x) ) && c(x) ) && d(x)
a(x) && ( b(x) && ( c(x) && d(x) ) )
这导致了这种评估顺序:a b c d
ps(x)&&&……
扩展到
( ( a(x) && b(x) ) && c(x) ) && d(x)
a(x) && ( b(x) && ( c(x) && d(x) ) )
这导致了相同的评估顺序:a b c d
这不会改变任何关于短路的情况;一旦一个为假,评估就会停止。我不认为
ps(x)&&&……
或…&&&ps(x)
更改了&&&
操作的关联性。那么,为什么期望不同的行为?@prog fh这两种形式正是在一个方向或另一个方向上施加关联性。但是,只有两个参数,这会发生什么变化?(从三个参数开始,我看到区别)我确实使用了一个不好的术语:不是关联性,而是求值顺序。@prog fh我想我已经理解了我的错误。我错误地期望求值顺序在这两种形式中被镜像,就像关联性被镜像一样。