В C ++ 11 это не рекомендуется:
void foo() throw();
и заменен
void foo() noexcept;
В Эта статья объясняется, что причина этого (среди прочего, сводится к тому же) заключается в том, что
Спецификации исключений C ++ проверяются во время выполнения, а не во время компиляции, поэтому они не дают программисту гарантий того, что все исключения были обработаны.
Хотя для меня это имеет смысл, я не понимаю, почему throw()
был динамически проверен в первую очередь, или почему noexcept
не предоставляет исключений, кроме звонка std::terminate
вместо обычного раскручивания стека (что на самом деле не является надежной гарантией IMO).
Не было бы возможно проверить, выбрасываются ли исключения во время компиляции и сбой компиляции, если это произойдет? На мой взгляд, есть в основном три случая:
void foo() noexcept
{
// 1. Trivial case
throw myexcept();
// 2. Try-catch case
// Necessary to check whether myexcept is derived
// from exception
try
{
throw myexcept();
}
catch(exception const & e)
{}
// 3. Nested function call
// Recursion necessary
bar();
}
С шаблонами в C ++, создаваемыми для каждого типа, компиляция приложений в любом случае занимает бесконечно — так почему бы не изменить noexcept
заставить компилятор проверить, генерируются ли исключения во время компиляции?
Единственная трудность, которую я вижу, состоит в том, что функция может выдавать или не выдавать в зависимости от состояний времени выполнения, но этой функции нельзя разрешать вызывать себя noexcept
во всяком случае, на мой взгляд.
Я что-то упустил, или намеревался не увеличивать время компиляции дальше, или облегчить задачу разработчикам компиляторов?
Я думаю, что во многом это объясняется тем, что при определении спецификаций исключений авторы компиляторов сильно отставали от кривой мощности. Реализация C ++ 98 настолько сложна, что когда-либо один компилятор, который даже утверждал реализовать все его возможности. Любой другой компилятор исключил хотя бы одну важную функцию, которая была включена в стандарт. Наиболее честно признавалось, что они упустили значительно больше, чем это.
Вы также должны иметь в виду, что спецификации динамических исключений также были значительно сложнее, чем просто throw()
, Это позволяет программисту указывать произвольный набор типов, которые могут быть выброшены. Хуже того, указав, что функция может бросить foo
означает, что он также может выбросить что-нибудь из foo
также.
Статическое применение спецификаций исключений могло бы быть выполнено, но это, несомненно, добавило бы немного дополнительной работы, и никто не был уверен, какую пользу (если таковая имеется) это даст. В этих обстоятельствах я думаю, что большинству было довольно легко подумать, что статическое принудительное применение было чем-то, что могло бы потребоваться позже, если, казалось, было достаточно использования, чтобы оправдать работу. Переход от принудительного исполнения во время выполнения к времени компиляции не потребует изменения существующего кода, а только существующих реализаций.
Другое дело, что я не уверен, что когда-либо сильный поддержка спецификаций исключений в любом случае. Я думаю, что было общее согласие по основной идее, но когда вы приступите к ней, вероятно, меньше о деталях.
Итог: было легко назначить только динамическое правоприменение и оставить статическое правоприменение на потом (если вообще было). Оказывается, статическое правоприменение, вероятно, в действительности не добавит столько положительного в любом случае, так что его обязательство, вероятно, в любом случае не достигло бы большого успеха.
Других решений пока нет …