如何在“折叠表达式”中也可以使用“短路评估”?

编程入门 行业动态 更新时间:2024-10-14 08:23:09
本文介绍了如何在“折叠表达式”中也可以使用“短路评估”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 #include <type_traits> #define FORWARD(arg)\ std::forward<decltype(arg)>(arg) template<typename... Args> constexpr bool AndL(Args&&... args) { return (... && FORWARD(args)); } template<typename... Args> constexpr bool AndR(Args&&... args) { return (FORWARD(args) && ...); } int main() { bool* pb = nullptr; false && (*pb = true); // ok at runtime. AndL(false, (*pb = true)); // error at runtime! AndR(false, (*pb = true)); // error at runtime! }

传统的&

The traditional && operator supports short-circuit evaluation, so false && (*pb = true) will be ok at runtime, but the following two cases are not.

如何使电路评估也可以在折叠表达式中使用?

How to make short-circuit evaluation also available in fold expressions?

推荐答案

这里的问题仅仅是对实际情况的误解。

The problem here is just a misconception of what's actually happening.

如何进行短路评估

在折叠表达式中可以使用 。 (args& ... ...)遵循与(a&& b& c& & d)。也就是说,仅在 a , b 和 c 都评估为真实。

It is available in fold expressions. (args && ... ) follows the exactly the same rules as (a && b && c && d). That is, d will only be evaluated if a, b, and c all evaluate to truthy.

这不是您两种情况之间的实际差异。

That's not the actual difference between your two cases.

false && (*pb = true); // ok at runtime. AndL(false, (*pb = true)); // error at runtime!

虽然折叠表达式与非折叠表达式的功能完全相同,但两者之间有一个重要区别两个陈述。第一个只是一个语句表达式,第二个是函数调用。并且必须在主体开始之前对所有函数参数进行求值。

While fold expressions do exactly the same thing as their non-fold counterparts, there's one important difference between these two statements. The first is just a statement-expression, the second is a function call. And all function arguments must be evaluated before the start of the body begins.

所以第二个等效于:

auto&& a = false; auto&& b = (*pb = true); (FORWARD(a) && FORWARD(b));

是导致问题的顺序,而不是折叠表达式(请注意: b 可以在 a 之前进行评估)。

It's that ordering that is causing the problem, not the fold expression (note: b could be evaluated before a).

为了使其透明,您真正需要的是惰性参数。这是几种语言的功能(例如 Scala ),但不是C ++语言。如果您需要懒惰,则最好的办法是将所有内容包装在一个lambda中:

In order to make this transparent, what you really need are lazy arguments. This is a feature in several languages (e.g. Scala), but not in C++. If you need laziness, the best you could do is wrap everything in a lambda:

template<typename... Args> constexpr bool AndL(Args&&... args) { return (... && FORWARD(args)()); } AndL([]{ return false; }, [&]{ return *pb = true; });

然后您可以使这个任意复杂-也许只是拆开那些可调用的类型,否则假设他们是傻子:

You could then make this arbitrarily complex - maybe only "unwrap" those types that are callable, otherwise assume that they're bool:

template <class T, std::enable_if_t<std::is_invocable<T>::value, int> = 0> bool unwrap(T&& val) { return std::forward<T>(val)(); } template <class T, std::enable_if_t<std::is_convertible<T, bool>::value, int> = 0> bool unwrap(T&& val) { return std::forward<T>(val); } template<typename... Args> constexpr bool AndL(Args&&... args) { return (... && unwrap(FORWARD(args))); } AndL(false, [&]{ return *pb = true; });

但实际上,要点是函数参数求值先于函数体,而问题不在于折叠表达式本身。

But really, the main point is that function argument evaluation precedes the function body, and the issue is not the fold expression itself.

更多推荐

如何在“折叠表达式”中也可以使用“短路评估”?

本文发布于:2023-11-12 10:33:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1581238.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:可以使用   表达式   中也   如何在

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!