通过使用函子数组来摆脱开关情况

Get rid from switch case by using array of functors

本文关键字:开关 情况 数组      更新时间:2023-10-16

我想去掉下面例子中的开关情况:

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)?

您不需要绑定任何内容。

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

您也不需要函子对象的数组。函数指针对于您所展示的逻辑来说是很好的。

bool (*(checks[]))(double, double) = { /* ... */ };
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和上面一样简单,并且没有状态,你可以用bool(*)(double, double)(一个原始函数指针)代替std::function<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);

其中代码在测试中流动,并且只有在前一个测试失败并报告错误时才执行某些操作。