Информация об изменениях

Сообщение Re: Потрея типа исключения от 25.08.2014 8:17

Изменено 25.08.2014 8:20 Кодт

Здравствуйте, ML380, Вы писали:

ML>Будет ли в данном случае потерян тип исключения при последующей ловле?


Будет, потому что throw кидает значение. Произойдёт банальное копирование со срезкой.

ML>Есть ли отличия данноного кода от просто "throw"?


Собственно, вот они и есть. "просто throw" продолжает работать со старым экземпляром, что позволяет делать, например, такой диспетчер исключений.
void detailed_panic()
{
  try { throw; } // запускаем сопоставление типа
  catch(Foo const& e) { ..... }
  catch(Bar const& e) { ..... }
  .....
  // если дефолтная ветка catch(...) ничего содержательного не делает, можно её не писать
  // из любой ветки можно пробросить исключение выше-дальше с помощью throw;
  // или бросить новое ислючение throw Xyz(......);
}

void alfa(.....)
{
  try { ..... } // делаем что-то полезное
  catch(...) { detailed_panic(); }
}
void beta(.....)
{
  try { ..... }
  catch(...) { detailed_panic(); } // повторно используем код обработки
}

В противном случае пришлось бы вывернуть код наизнанку, прибегнув к функциям (или макросам) высшего порядка
template<class Fun> void run_and_catch(Fun&& fun)
{
  try { fun(); }
  catch(Foo const& e) { ..... }
  catch(Bar const& e) { ..... }
  .....
}

void alfa(.....)
{
  run_and_catch( [&]() { ..... } );
}
// или, по старому стилю,
void beta_impl(.....) { ..... }
void beta()
{
  run_and_catch( boost::bind(beta_impl, .....) );
}
Re: Потрея типа исключения
Здравствуйте, ML380, Вы писали:

ML>Будет ли в данном случае потерян тип исключения при последующей ловле?


Будет, потому что throw кидает значение. Произойдёт банальное копирование со срезкой.

ML>Есть ли отличия данноного кода от просто "throw"?


Собственно, вот они и есть. "просто throw" продолжает работать со старым экземпляром, что позволяет делать, например, такой диспетчер исключений.
void detailed_panic()
{
  try { throw; } // запускаем сопоставление типа
  catch(Foo const& e) { ..... }
  catch(Bar const& e) { ..... }
  .....
  // если дефолтная ветка catch(...) ничего содержательного не делает, можно её не писать
  // из любой ветки можно пробросить исключение выше-дальше с помощью throw;
  // или бросить новое ислючение throw Xyz(......);
}

void alfa(.....)
{
  try { ..... } // делаем что-то полезное
  catch(...) { detailed_panic(); }
}
void beta(.....)
{
  try { ..... }
  catch(...) { detailed_panic(); } // повторно используем код обработки
}

В противном случае пришлось бы вывернуть код наизнанку, прибегнув к функциям (или макросам) высшего порядка
template<class Fun> void run_and_catch(Fun&& fun)
{
  try { fun(); }
  catch(Foo const& e) { ..... }
  catch(Bar const& e) { ..... }
  .....
}

void alfa(.....)
{
  run_and_catch( [&]() { ..... } );
}
// или, по старому стилю,
void beta_impl(.....) { ..... }
void beta()
{
  run_and_catch( boost::bind(beta_impl, .....) );
}

// или на макросах ( узнаёте старый злобрый MFC? )

#define BEGIN_RUN_AND_CATCH() try {
#define END_RUN_AND_CATCH()   } CATCH_FOO() CATCH_BAR() CATCH_OTHERWISE()
#define CATCH_FOO() catch(Foo const& e) { ..... }
// и т.д.

void alfa(.....)
{
  BEGIN_RUN_AND_CATCH()
  .....
  END_RUN_AND_CATCH()
}
void beta(.....)
{
  BEGIN_RUN_AND_CATCH()
  .....
  END_RUN_AND_CATCH()
}