Фильтр исключений
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 02.02.17 12:00
Оценка:
Привет всем.

Засунув в десяток catch-ей

catch(const std::exception& e)
{
 if(!<некоторое условие>)
  throw;

 //....
}


Задумался — а зачем вообще заходит в catch?

Вопрос — планируется ли в плюсах поддержка "фильтров исключений"?

Ну, то есть, привязка к catch дополнительного вычисляемого условия.

Типа catch_if какой-нибудь?

Пользоваться я этим catch_if все равно ближайшие лет 15 не буду, но интересно

---
Просьба не предлагать организовывать две ветки кода.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Фильтр исключений
От: B0FEE664  
Дата: 02.02.17 15:13
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Вопрос — планируется ли в плюсах поддержка "фильтров исключений"?

Есть фильтр по типу исключений. В if(!<некоторое условие>) throw; можно поменять тип. На мой взгляд этого достаточно, а про то, что планируется я не в курсе.
И каждый день — без права на ошибку...
Re: Фильтр исключений
От: Alexander G Украина  
Дата: 02.02.17 18:58
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Вопрос — планируется ли в плюсах поддержка "фильтров исключений"?


КД>Ну, то есть, привязка к catch дополнительного вычисляемого условия.


В Structured Exception Handling всегда можно было (хотя это не плюсы, конечно же):

__try
{
    RaiseException(0xE3000001, 0, 0, NULL);
}
__except ((GetExceptionCode() == 0xE3000001 && <некоторое условие>) 
             ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{

}
Русский военный корабль идёт ко дну!
Re: Фильтр исключений
От: zaufi Земля  
Дата: 02.02.17 19:43
Оценка: +1
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Привет всем.


КД>Засунув в десяток catch-ей


ну если эти catch'и одной кучей подряд идут, то:
try
{
    // сильно много исключений вылетает отсюда
}
catch(...)
{
    if (!<некоторое условие>)
        throw;

    // ок, посмотрим что же там произошло и решим что делать...
    try
    {
        throw;
    }
    catch (const database::exception& e)
    {
        // 
    }
    catch (const http::exception& e)
    {
        // 
    }
    catch (const std::runtime_exception& e)
    {
        // 
    }
    catch (const std::exception& e)
    {
        // 
    }
}


если нет... т.е. ты порефачил реальную кучу файлов/функций с одиночными catch блоками... то запись
catch (const std::exeception& e) if (some_condition)
{
}

или как бы там этот синтаксический сахар не выглядел... не особо лучше/короче приведенного тобой кода -- так или иначе `some_condition` нужно написать,
а в твоем коде, IMHO, синтаксического шума не сказать что много, чтобы запариваться на "фильтры исключений" и прочий сахар, да еще и добавляя что-то в язык!

КД>Задумался — а зачем вообще заходит в catch?


"заходить" в catch в целом то, не страшно, когда у тебя таблицы... с сахаром или без, тип исключения тоже нужно будет проверять по любому... и не факт что эта проверка "дороже" чем вычисление "некоторого условия" %)

КД>Вопрос — планируется ли в плюсах поддержка "фильтров исключений"?


если ты не напишешь офигительный proposal в комитет, IMHO наврядли кто-то будет рассматривать подобное улучшение в языке %)

КД>Просьба не предлагать организовывать две ветки кода.


это как?

ЗЫ кстати весь код ниже коммента "// ок, ..." можно вынести в отдельную функцию и реюзать, если подобных блоков catch много где встречается...
Re: Фильтр исключений
От: kov_serg Россия  
Дата: 02.02.17 20:07
Оценка: +1
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Засунув в десяток catch-ей


КД>
КД>catch(const std::exception& e)
КД>{
КД> if(!<некоторое условие>)
КД>  throw;

КД> //....
КД>}
КД>

КД>Задумался — а зачем вообще заходит в catch?

Лучше сделайте отдельный обработчик чем копипастить
try {
  ...
} catch(...) { 
  context.analyze_exception(); 
}
...
void Context::analyze_exception() {
  try { throw; } 
  catch(const std::exception &e) {
    // complex logic here
    ...
  }
  catch(SomethingElse &se) {
  }
  ...
}
Re: Фильтр исключений
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 03.02.17 05:42
Оценка: +1
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Вопрос — планируется ли в плюсах поддержка "фильтров исключений"?

Дык по типу исключения всё фильтруется на ура. Просто ловишь исключение конкретного типа и обрабатываешь.
КД>Ну, то есть, привязка к catch дополнительного вычисляемого условия.
КД>Типа catch_if какой-нибудь?
Зачем? У тебя есть желание построить логику работы программы на исключениях? Это неправильно.
Sic luceat lux!
Re: Фильтр исключений
От: Кодт Россия  
Дата: 06.02.17 13:07
Оценка: 3 (1)
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Вопрос — планируется ли в плюсах поддержка "фильтров исключений"?

КД>Ну, то есть, привязка к catch дополнительного вычисляемого условия.
КД>Типа catch_if какой-нибудь?

Тут надо заметить, что гребёнка catch(Type){if(!test)throw;...} не эквивалентна гребёнке catch_if(Type,test){...}

try { // какой-то внешний блок
  try { foo(); }
  catch(A a) { if(!test_a()) throw; accept_a(); } // по else прыгнем сразу на catch(D) и далее
  catch(B b) { if(!test_b()) throw; accept_b(); } // по else прыгнем сразу на catch(D) и далее
  catch(...) { accept_c(); }
}
catch(D d) { accept_d(); }
catch(...) { accept_e(); }


try { foo(); }
catch_if(A a, test_a()) { ... }
catch_if(B b, test_b()) { ... }
catch(...) { accept_c(); }

// почти эквивалентно
try {
  try {
    try { foo(); }
    catch(A a) { if(!test_a()) throw; accept_a(); }
  } catch(B b) { if(!test_b()) throw; accept_b(); }
}   catch(...) { accept_c(); }


Почти — потому что надо различать, когда мы делаем throw с целью продолжить диспетчеризацию, а когда новое исключение вылетает из недр accept...
А ещё, исключение может вылететь из test...

Наверно, можно как-то выкрутиться с помощью магии препроцессора, шаблонов и лямбд, чтобы синтаксис гребёнки превратить в семантику лестницы.
Что-то в таком роде
template<class FUN, class... FUNS> void flat_catch(FUN&& f1, FUNS&&... fs) {
  try { f1(); }
  catch(...) { flat_catch(std::forward<FUNS>(fs)...); }
}
void flat_catch() { throw; }

int main() {
  try { foo(); }
  catch(...) { flat_catch(
      [&]() { throw; }
    , [&]() { try{ throw; } catch(A a) { if(!test_a()) throw; accept_a(); }
    , [&]() { try{ throw; } catch(B b) { if(!test_b()) throw; accept_b(); }
    , [&]() { try{ throw; } catch(...) {                      accept_c(); }
  }

#define TRY try {
#define BEGIN_CATCHES } catch(...) { flat_catch( [&]() { throw;
#define CATCH_IF(T,C) } , [&]() { try{ throw; } catch(T) { if(!(C)) throw;
#define END_CATCHES   } }

  try
    foo();
  BEGIN_CATCHES
  CATCH_IF(A a, test_a())
    accept_a();
  CATCH_IF(B b, test_b())
    accept_b();
  CATCH_IF(..., true)
    accept_c();
  END_CATCHES
}
Перекуём баги на фичи!
Re[2]: Фильтр исключений
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.02.17 13:24
Оценка:
Здравствуйте, Кодт, Вы писали:

КД>>Вопрос — планируется ли в плюсах поддержка "фильтров исключений"?

КД>>Ну, то есть, привязка к catch дополнительного вычисляемого условия.
КД>>Типа catch_if какой-нибудь?

К>Наверно, можно как-то выкрутиться с помощью магии препроцессора, шаблонов и лямбд, чтобы синтаксис гребёнки превратить в семантику лестницы.

К>Что-то в таком роде

Ох, нет...

Магию и компанию — фтопку.

Чем проще, тем лучше.

  Оставил самый первый вариант
   try
   {
    m_connection->dangerous__GetActiveRemoteCn()->GetColumns
     (op_ctx,
      &m_stmt_data->m_handle,
      xrow->get_public_xsqlda());
   }
   catch(const std::exception& e)
   {
    if(!m_connection->dangerous__get_cns().err_rules__explain_dbms_error())
     throw;

    t_ibp_error exc(e);

    exc.add_error(exc.com_code(),ibp_mce_cmd_describe_columns_0);

    exc.raise_me();
   }//catch
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Фильтр исключений
От: Кодт Россия  
Дата: 06.02.17 16:04
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Ох, нет...

КД>Магию и компанию — фтопку.
КД>Чем проще, тем лучше.
КД>Оставил самый первый вариант

Поскольку здесь ровно один catch, то всё, что нужно проверить — это гигиена повторных исключений.
Что если внутри catch-блока что-то вылетит, то вызывающая сторона будет к этому так же готова, как к необработанному исключению из try-блока. (Либо гарантировать, что из catch ничего, кроме "throw;" не вылетит).

А вот что насторожило, — это то, что исключение размазано: половина информации находится собственно в объекте-наследнике std::exception, вторая половина — в каких-то свойствах m_connection.
Почему бы в тех местах, где взводится флажок err_rules__explain_dbms_error(), не кидать исключение соответствующего типа? И затем ловить его.

Ну и не забываем про множественное наследование.
class my_error_base : public std::runtime_error { ..... };

// семейство исключений, по одному признаку на класс
class my_dbms_error : public my_error_base { ..... };
  class my_dbms_sql_error : public my_dbms_error { ..... };
class my_network_error : public my_error_base { ..... };

// семейство исключений, по сочетанию флагов
class my_flag1_error : public virtual my_error_base {};
class my_flag2_error : public virtual my_error_base {};
class my_flag4_error : public virtual my_error_base {};

class my_flags_1_and_2_error : public my_flag1_error, public my_flag2_error {};


try {
  .....
  throw my_flags_1_and_2_error(the_connection, other_helpful_stuff);
  .....
} catch(const my_flag1_error& e) {
  const& my_error_base meb = e;  // и извлечём оттуда the_connection и т.п.
  .....
}
Перекуём баги на фичи!
Re: Фильтр исключений
От: rg45 СССР  
Дата: 06.02.17 16:09
Оценка: 1 (1)
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Засунув в десяток catch-ей

КД>...
КД>Задумался — а зачем вообще заходит в catch?

Несколько лет назад здесь проскакивала достаточно элегантная реализация фильтра исключений. Найти ссылку сходу не удалось, но идея была примерно такая:

(не компилировал)

void filter_current_exception()
{
  try
  {
    throw;
  }
  catch (const Exception1& ex)
  {
    . . .
  }
  catch (const Exception2& ex)
  {
    . . .
  }
  catch (const Exception3& ex)
  {
    . . .
  }
}

void foo()
{
  try
  {
    do_something_1();
  }
  catch (...)
  {
    filter_current_exception();
  }
}

void bar()
{
  try
  {
    do_something_2();
  }
  catch (...)
  {
    if (some_condition())
    {
      filter_current_exception();
    }
  }
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: Фильтр исключений
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.02.17 16:31
Оценка:
Здравствуйте, Кодт, Вы писали:

К>А вот что насторожило, — это то, что исключение размазано: половина информации находится собственно в объекте-наследнике std::exception, вторая половина — в каких-то свойствах m_connection.


В наследнике std::exception находится описание ошибки (в нем, вообще говоря, "возится" коллекция ошибок).

А в connection находятся настройки, среди которых есть настройка детализации описания ошибок.

Предвижу вопрос — "почему бы не выкидывать полное описание ошибки, а в точке обработки урезать лишнее?"

Ответ — (1) все не так просто. (2) ни осилил.

К>Почему бы в тех местах, где взводится флажок err_rules__explain_dbms_error(), не кидать исключение соответствующего типа? И затем ловить его.


Оно все ловится на уровне интерфейса COM-объекта, перепаковывается в COM-объект, который потом возвращается клиенту через SetError.

К>Ну и не забываем про множественное наследование.


Это все красиво. Но не более
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[2]: Фильтр исключений
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.02.17 16:37
Оценка: +1
Здравствуйте, rg45, Вы писали:

КД>>Задумался — а зачем вообще заходит в catch?


R>Несколько лет назад здесь проскакивала достаточно элегантная реализация фильтра исключений. Найти ссылку сходу не удалось, но идея была примерно такая:


Она у меня используется. В полный рост.

Re: подход к try-catch (0xDEADBEEF)
Автор: 0xDEADBEEF
Дата: 05.10.05


Славное было время ...
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Фильтр исключений
От: rg45 СССР  
Дата: 06.02.17 17:45
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Re: подход к try-catch (0xDEADBEEF)
Автор: 0xDEADBEEF
Дата: 05.10.05


КД>Славное было время ...


Как время летит!
--
Не можешь достичь желаемого — пожелай достигнутого.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.