【问题标题】:branching based on two boolean variables基于两个布尔变量的分支
【发布时间】:2011-08-05 12:31:08
【问题描述】:

假设我有两个布尔变量,我想根据它们的值做完全不同的事情。实现这一目标的最干净的方法是什么?

变体 1:

if (a && b)
{
    // ...
}
else if (a && !b)
{
    // ...
}
else if (!a && b)
{
    // ...
}
else
{
    // ...
}

变体 2:

if (a)
{
    if (b)
    {
        // ...
    }
    else
    {
        // ...
    }
}
else
{
    if (b)
    {
        // ...
    }
    else
    {
        // ...
    }
}

变体 3:

switch (a << 1 | b)
{
case 0:
    // ...
    break;

case 1:
    // ...
    break;

case 2:
    // ...
    break;

case 3:
    // ...
    break;
}

变体 4:

lut[a][b]();

void (*lut[2][2])() = {false_false, false_true, true_false, true_true};

void false_false()
{
    // ...
}

void false_true()
{
    // ...
}

void true_false()
{
    // ...
}

void true_true()
{
    // ...
}

对于普通程序员来说,变体 3 和 4 是否过于棘手/复杂?我错过了任何其他变体?

【问题讨论】:

  • 你为什么想做 3 或 4?对我来说看起来很可怕:)

标签: c++ if-statement function-pointers switch-statement control-flow


【解决方案1】:

第一个变体最清晰易读,但可以调整:

if (a && b) {
    // ...
} else if (a) { // no need to test !b here - b==true would be the first case
    // ...
} else if (b) { //no need to test !a here - that would be the first case
    // ...
} else { // !a&&!b - the last remaining
    // ...
}

【讨论】:

  • 一旦整个语句不适合一个屏幕,它就会变得非常难以阅读。我一点也不明白。
  • @Alex:没关系,我最终根本不需要第四个案例,现在整个内容适合 13 行(其中 6 行只是大括号)。
  • @Alexandre C:所以不要编写一个屏幕不适合的函数;-p
  • @Alexandre:为什么这不适合一个屏幕?只需在点所在的位置添加函数调用,它就非常紧凑和可读。
  • 如果a 为假,编译器是否足够聪明,可以跳过第二次检查并直接跳到第三次检查?
【解决方案2】:

你忘了:

if (a) a_true(b);
else a_false(b);

这可能是适用时的最佳选择,并且当您真正需要 4 种不同的行为时。

如果你有超过 2 个布尔值,如果我有 2^n 种不同的行为不能像上面那样很好地分解,我会将其视为代码异味。那我可能会考虑做:

enum { case1, case2, ... }

int dispatch_cases(bool a, bool b, bool c, ..., bool z);

switch (dispatch_cases(a, b, ..., z))
{
case case1:
    ...
};

但没有上下文,很难判断这种复杂性是否必要。

【讨论】:

    【解决方案3】:

    恕我直言,我会选择variant 3。因为就我个人而言,我不喜欢if/else 检查是否相等。它明确指出只有四种可能性。

    一个小的修改是:

    inline int STATES(int X, int Y) { return (X<<1) | Y; }
    // ...
    switch (STATES(a,b))
    

    为了更美观,您也可以将0,1,2,3 替换为enum

    enum States {
      NONE,
      ONLY_B.
      ONLY_A,
      BOTH
    }; 
    

    【讨论】:

    • 然而,它未能清楚地说明该位的用途。这就是我不喜欢它的原因。
    • @Martinho,是的,这是真的。我们可以在那里有一些东西。我已尝试在编辑版本中传达您的信息。
    • true 的定义不为零。它不一定是没有一些额外工作的,比如(X?2:0)|(Y?1:0)
    【解决方案4】:

    对于两个布尔值,它们中的任何一个都是好的和合理的。大家可以根据自己的喜好来选择。

    但是,如果有两个以上的布尔值,比如 四个 布尔值,那么我个人会使用查找表,我会这样做:

    typedef void (*functype)();
    
    //16 functions to handle 16 cases!
    void f0() {}
    void f1() {}
    //...so on
    void f15() {}
    
    //setup lookup table
    functype lut[] = 
    {
        f0,   //0000 - means all bool are false
        f1,   //0001
        f2,   //0010
        f3,   //0011
        f4,   //0100
        f5,   //0101
        f6,   //0110
        f7,   //0111
        f8,   //1000
        f9,   //1001
        f10,  //1010
        f11,  //1011
        f12,  //1100
        f13,  //1101
        f14,  //1110
        f15   //1111 - means all bool are true
    };
    
    lut[MakeInt(b1,b2,b3,b4)](); //call
    

    MakeInt() 好写:

    int MakeInt(bool b1, bool b2, bool b3, bool b4)
    {
       return b1 | (b2<<1) | (b3 <<2) | (b4<<3);
    }
    

    【讨论】:

    • 如果有两个以上的布尔值,我会尝试找出如何摆脱它们。
    • @Alexandre:即使我会尝试摆脱它们。但如果我失败了呢?那我会选择这种方式。
    猜你喜欢
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 2021-04-10
    • 2011-05-25
    • 2018-07-22
    相关资源
    最近更新 更多