Ответ 1
Спецификаторы исключений были устаревшими, поскольку спецификаторы исключений, как правило, представляют собой ужасную идею. noexcept
был добавлен, потому что это одно полезное использование спецификатора исключения: зная, когда функция не будет генерировать исключение. Таким образом, он становится двоичным выбором: функции, которые будут бросать, и функции, которые не будут выбрасываться.
noexcept
, а не просто удаление всех спецификаторов throw, отличных от throw()
, потому что noexcept
более мощный. noexcept
может иметь параметр, который время компиляции разрешается в логическое. Если логическое значение истинно, то noexcept
хранится. Если логическое значение false, то noexcept
не встает, и функция может отбрасывать.
Таким образом, вы можете сделать что-то вроде этого:
struct<typename T>
{
void CreateOtherClass() { T t{}; }
};
Выбрасывает ли CreateOtherClass
исключения? Это может быть, если конструктор T
по умолчанию может. Как мы расскажем? Вот так:
struct<typename T>
{
void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};
Таким образом, CreateOtherClass()
будет бросать iff, который генерирует конструктор по умолчанию данного типа. Это устраняет одну из основных проблем с спецификаторами исключений: их неспособность распространять стек вызовов.
Вы не можете сделать это с помощью throw()
.