Los especificadores de excepciones quedaron obsoletos porque los especificadores de excepciones son generalmente una idea terrible . noexceptse agregó porque es el único uso razonablemente útil de un especificador de excepción: saber cuándo una función no lanzará una excepción. Por lo tanto, se convierte en una opción binaria: funciones que arrojarán y funciones que no lanzarán.
noexceptse agregó en lugar de simplemente eliminar todos los especificadores de lanzamiento que no sean throw()porque noexceptes más poderoso. noexceptpuede tener un parámetro que en tiempo de compilación se resuelve en un booleano. Si el booleano es verdadero, entonces se noexceptpega. Si el booleano es falso, entonces noexceptno se pega y la función puede lanzar.
Por lo tanto, puede hacer algo como esto:
struct<typename T>
{
void CreateOtherClass() { T t{}; }
};
¿ CreateOtherClassLanza excepciones? Podría, si Tel constructor predeterminado puede. ¿Cómo lo contamos? Me gusta esto:
struct<typename T>
{
void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};
Por lo tanto, CreateOtherClass()arrojará iff arroja el constructor predeterminado del tipo dado. Esto soluciona uno de los principales problemas con los especificadores de excepciones: su incapacidad para propagarse por la pila de llamadas.
No puedes hacer esto con throw().
noexceptpuede incurrir en comprobaciones de tiempo de ejecución. La principal diferencia entre ellos es que rompernoexceptcausasstd::terminatey romperthrowcausasstd::unexpected. También un comportamiento de desenrollado de pila ligeramente diferente en estos casos.