【问题标题】:Is it possible to define boolean expressions that can be evaluated later?是否可以定义可以稍后评估的布尔表达式?
【发布时间】:2017-11-24 04:34:35
【问题描述】:

希望实现一种动态表达式,以便稍后在调用时计算布尔值。

condition &&= condition2; //not evaluated just yet
condition ||= condition3;    

if (condition)    //evaluated now
   do this;
else
   do this;

例如,我在整个代码中使用相同的条件,如果我可以只调整一个语句或添加更多语句,即使程序运行也会更容易。

conditions = (x>50 && y>200) && (type == MONKEY);
conditions &&= (x<75 && y<250);

以后在代码中

if (conditions)
    cout<<"Hello!";

edit:条件应在 if 语句中进行评估。

【问题讨论】:

  • 您可以使用运营商&amp;=
  • 所以我只是想知道下面的答案是不是这些在赋值时评估表达式而不是 if 语句?我正在寻找在 if 语句中进行评估的功能。
  • 有趣。为什么?即,您为什么要在评估事情时关心?是否存在我们不知道的线程上下文?
  • 它只是一个非常简单的程序,但我正在做的是通过几个 For 循环并避免某些情况。但我不断发现更多这样的情况,将它们放在一个地方会更容易。 示例:通过窗口中的像素移动并避开窗口的某些区域。但总的来说,我只是想看看这是否可能。
  • 如果你在移动,写一个移动函数,比如向左移动等等,然后跳过这些位 - 或者保持不动,或者其他什么?

标签: c++ conditional-statements lazy-evaluation


【解决方案1】:

使用 && 和 & 时要非常小心


原因一

扩展假设(并且在语法上无效)

condition &&= condition2;

condition = condition && condition2;

揭示了一个微妙之处:如果 conditionfalsecondition2不会被评估。


原因 2

&amp;&amp;&amp; 对于整数类型也有不同的行为,例如0b01 &amp; 0b1000b01 &amp;&amp; 0b10true(这里我使用 C++14 二进制文字)。


结论

所以我倾向于压缩

if (condition = condition && condition2){
    // do this
} else {
    // do this
}

其中condition2 仅在conditiontrue 时才被评估

【讨论】:

  • 更不用说有些类型可以在上下文中转换为 bool 可能会与 &amp;= 一起爆炸
  • @PasserBy:确实。将其添加到最后。
  • IIRC 短路仅适用于非用户定义的类型,不是吗?因此,如果在哪里制作 deferred_bool,那么如果实施得当,&amp;=&amp;&amp; 将不会有任何问题
  • 不正确。仅当 && 对于该类型 重载 时,才会删除短路。与其做所有这些,不如编写foo(condition, condition2),分别通过引用和常量引用获取条件,修改第一个参数,然后返回condition
【解决方案2】:

这里明智的解决方案是为这些条件创建命名函数并在必要时调用它们。


也就是说……

有没有可能[..]

当然。要推迟评估,只需将您的条件包装在 (lambda) 函数中。概念证明:

#include <functional>
#include <iostream>

template<typename F, typename G>
auto and_also (F f, G g) {
  return [=]() {
    bool first = f();
    if (! first) return false;
    return static_cast<bool>(g());
  };
}

int main () {
  int dummy = -1;
  std::function<bool()> condition = [&](){return dummy > 0;};
  condition = and_also(condition, [&](){return dummy < 42;});
  dummy = 21;
  if (condition()) std::cout << "in range" << std::endl;
}

【讨论】:

    【解决方案3】:

    为了解决用例,您在评论中提到:

    示例:在窗口中移动像素并避开窗口的某些区域。

    出于可读性的原因,我建议您定义一个函数,例如,像这样(伪代码)示例:

    bool is_in_rect(point2i p, rect2i rect) {
        // check x range
        if (p.x >= rect.x1 && p.x < rect.x2)
            return true;
        // check y range
        if (p.y >= rect.y1 && p.y < rect.y2)
            return true;
        return false;
    }
    

    您可以根据需要为特殊情况添加功能:

    bool is_in_monkey_rect(point2i p, rect2i rect) {
        return rect.type == MONKEY && is_in_rect(p, rect);
    }
    

    但总的来说,我只是想看看这是否可能。

    除了委托给一个函数,您可能会使用宏来模拟这种惰性求值。但我不建议这样做。

    请注意,根据问题的实际性质,调整迭代模式可能更有意义,而不是迭代所有数据并检查每个像素的相关性。

    【讨论】:

    • 确实如此。我试着不去想 M 字。
    【解决方案4】:

    在一个地方做某事的一种常见方法是制作一个函数,这样你就不会到处重复自己。

    例如,

    bool special_condition(bool current_condition, int x)
    {
        return current_condition && (x<75 && y<250);
    }
    

    在需要时允许这样做。

    if (special_condition(conditions))
        do_something();
    else
        do_something_else();
    

    当遇到 if 时会进行评估,但是,如果 current_condition 为 false 时仍会调用该函数,则不会短路。

    【讨论】:

    • 我认为这就是我所追求的。我可以创建一个递归函数并让它测试所有条件。
    • 没有短路可能会减慢您的速度……这取决于您的具体情况。
    【解决方案5】:

    Stefan 的简答,C++ 没有。

    &amp;= 期间计算表达式。

    短路表达式,例如如果aa &amp;&amp; b 等表达式中为假,则忽略b,通常可以在您的环境中进行配置,并且通常开启。

    如果您仍希望这样做,请改为创建一个评估函数。

    /安德斯

    【讨论】:

      猜你喜欢
      • 2013-10-23
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      • 2015-05-16
      • 2018-06-13
      • 2010-09-09
      • 1970-01-01
      • 2018-05-29
      相关资源
      最近更新 更多