传统的& 运算符支持短路评估,因此 false&& (* pb = true)在运行时可以,但以下两种情况不可行。
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.
更多推荐
如何在“折叠表达式”中也可以使用“短路评估”?
发布评论