Упростите 4, если / иначе проверяет два логических значения - PullRequest
1 голос
/ 13 января 2020

У меня в коде такая ситуация:

bool a, b, result;
... // a and b are set
if(!a &&! b)
    result = functionOne() ;
else if(!a && b)
    result = functionTwo();
else if(a &&! b)
    result = functionThree();
else
    result = functionFour();

Есть ли способ упростить / сократить этот код? Заранее спасибо!

Ответы [ 5 ]

2 голосов
/ 13 января 2020

Используйте переключатель:

 int index = 2*a + b;
 switch (index) {
     case 0: result = functionOne();  break;
     case 1: result = functionTwo();  break;
     case 2: result = functionThree();break;
     case 3: result = functionFour(); break;
 }
2 голосов
/ 13 января 2020

Поскольку обучение является вашей целью, вот «упрощение» с использованием таблицы поиска:

#include <iostream>

bool functionOne()
{
  std::cout << __FUNCTION__ << std::endl;
  return true;
}
bool functionTwo()
{
  std::cout << __FUNCTION__ << std::endl;
  return true;
}
bool functionThree()
{
  std::cout << __FUNCTION__ << std::endl;
  return true;
}
bool functionFour()
{
  std::cout << __FUNCTION__ << std::endl;
  return true;
}

int main()
{
  using F = bool (*)();
  constexpr F lookup[2][2] = {{functionOne, functionTwo},
                              {functionThree, functionFour}};

  bool a = true, b = false, result;
  result = lookup[a][b]();           // <- the simplification
}

печатает:

functionThree

, как и ожидалось.

Объяснение: он использует двумерный массив указателей на функции.

Примечание: он работает в соответствии со стандартом C ++, который явно говорит, что во время преобразования bool -> int (ваш индекс массива), значение false преобразуется в ноль, а значение true в единицу.

If the source type is bool, the value false is converted to zero and
the value true is converted to the value one of the destination type
(note that if the destination type is int, this is an integer
promotion, not an integer conversion).

https://en.cppreference.com/w/cpp/language/implicit_conversion

2 голосов
/ 13 января 2020

Этот вопрос действительно основан на мнениях, поэтому существует множество возможных решений, которые - в зависимости от индивидуальных предпочтений - могут быть выбраны.

Вы всегда можете проверить одну переменную в if, а затем использовать троичный оператор

 if (!a)
     result = (!b) ? functionOne() : functionTwo();
 else
     result = (!b) ? functionThree() : functionFour();

Это имеет (возможное) преимущество, заключающееся в необходимости оценивать каждый из !a и !b ровно один раз во время выполнения.

Если вы хотите устранить отрицания (некоторые могут посчитать, что это лучше для читабельности, особенно из-за того, что имена функций нередко подразумевают их упорядочение), код можно превратить в

 if (a)
     result = b ? functionFour() : functionThree();
 else
     result = b ? functionTwo() : functionOne();

, что приводит нас к возможностям исключения оператор if полностью.

 // with negation

 result = !a ? ((!b) ? functionOne() : functionTwo()) : 
              ((!b) ? functionThree() : functionFour());

 // without negation

 result = a ? (b ? functionFour() : functionThree()) : 
              (b ? functionTwo() : functionOne());

Другой вариант, который приходит на ум, будет

 int index = 2*a + b;
 if (index == 0)
     result = functionOne();
 else if (index == 1)
     result = functionTwo();
 else if (index == 2)
     result = functionThree();
 else if (index == 3)
     result = functionFour();

, который можно упростить, используя одномерный массив

  using func = bool(*)();    // C++11 and later.   typedef bool (*func)() for all C++ standards
  func table[] = {functionOne, functionTwo, functionThree, functionFour};
  result = table[2*a + b]();
2 голосов
/ 13 января 2020

Да, вы можете воспользоваться некоторыми последствиями:

bool a, b, result;
... // a and b are set
if(a && b)
    result = functionFour();
else if(b)
    result = functionTwo();
else if(a)
    result = functionThree();
else
    result = functionOne();

Объяснение: Если оба значения a и b не истинны, одно из них должно быть ложным. В этом случае, если b истинно, a должно быть ложным, поэтому нет необходимости оценивать его избыточно.

1 голос
/ 13 января 2020

Да, вы можете использовать троичный оператор :

bool a, b, result;
// a and b are set
result = a && b ? functionOne() : b ?functionTwo() : a ? functionThree() : functionFour();

Используйте его только для простых задач, а не для сложных, потому что он может очень быстро запутаться.

...