Я хотел бы избавиться от корпусов коммутаторов в приведенном ниже примере:
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
просты, как указано выше, и не имеют состояния, вы можете заменить 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);
где код протекает через тесты и только что-то делает, если предыдущий тест не прошел и сообщил об ошибке.