Избавьтесь от случая переключателя, используя массив функторов

0

Я хотел бы избавиться от корпусов коммутаторов в приведенном ниже примере:

for ( int i = 0; i < 7; ++i )
    {
            switch (i)
            {
            case 2: case 5: case 6:
                if (value < 0)
                {
                  reportError(param);
                  return;
                }
                break;
            case 3: case 4:
                if (value <= 0)
                {
                  reportError(param);
                  return;
                }
                break;
             default:
                ;
            }
    }

Я хотел бы сделать что-то вроде этого:

    |
                                                        |
                                                       '''   ---- (error)
                                                        '
std::binary_function<double, double, bool> checks[] = { 0, less_equal<double>(), 
                                                        less<double>(), less<double>(),
                                                        less_equal<double>(),
                                                        less_equal<double>(), 
                                                        0 } ; 

for(int i = 0; i < 7; ++i)
{
   if( bind2nd(checks[i], 0)(value) )    <----- error
   {
      reportError(param);
      return;
   }
}

Как я могу избавиться от корпусов коммутаторов (в C++ 98 и без использования boost)?

Теги:

2 ответа

1
Лучший ответ

Вам не нужно ничего связывать.

if (checks[i](value, 0))

Вам также не нужен массив объектов-функторов. Функциональные указатели отлично подходят для логики, которую вы показали.

bool (*(checks[]))(double, double) = { /* ... */ };
1
auto always_false = [](double, double) {return false;}
std::function<bool(double,double)> checks = {
  always_false,
  less_equal<double>(),
  less<double>(), less<double>(),
  less_equal<double>(), less_equal<double>(),
  always_false
};

for( int i = 0; i < 7; ++i )
{
  if (checks[i]( 0, value ))
  {
    reportError(param);
    return;
  }
}

если ваши checks просты, как указано выше, и не имеют состояния, вы можете заменить std::function<bool(double,double)> на bool(*)(double, double), указатель на сырую функцию. Это будет не менее эффективно.

Еще один способ приблизиться к этому - сделать ошибочное программирование.

boost::optional<ErrorMessage> err;
if (!err && test_1()) err = makeError(param);
if (!err && test_2()) err = makeError(param);
if (!err && test_3()) err = makeError(param);
// ...
if (err)
  reportError(*err);

где код протекает через тесты и только что-то делает, если предыдущий тест не прошел и сообщил об ошибке.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню