Existe-t-il une autre différence entre throw()
et noexcept
en plus d'être vérifiée respectivement au moment de l'exécution et de la compilation?
Wikipedia C++ 11 l'article suggère que les spécificateurs de lancement C++ 03 sont déconseillés.
Pourquoi donc, noexcept
est-il suffisamment capable de couvrir tout cela au moment de la compilation?
[Remarque: J'ai fait référence cette question et cet article , mais je n'ai pas pu obtenir la raison solide de la dépréciation.]
Les spécificateurs d'exceptions ont été déconseillés parce que les spécificateurs d'exceptions sont généralement une idée terrible . noexcept
a été ajouté car c'est la seule utilisation raisonnablement utile d'un spécificateur d'exception: savoir quand une fonction ne lèvera pas une exception. Ainsi, cela devient un choix binaire: les fonctions qui lanceront et les fonctions qui ne lanceront pas.
noexcept
a été ajouté au lieu de simplement supprimer tous les spécificateurs de lancer autres que throw()
car noexcept
est plus puissant. noexcept
peut avoir un paramètre qui se résout au moment de la compilation en booléen. Si le booléen est vrai, alors le noexcept
colle. Si le booléen est faux, alors le noexcept
ne colle pas et la fonction peut lancer.
Ainsi, vous pouvez faire quelque chose comme ceci:
struct<typename T>
{
void CreateOtherClass() { T t{}; }
};
CreateOtherClass
lève-t-il des exceptions? Il le pourrait, si le constructeur par défaut de T
le pouvait. Comment le savons-nous? Comme ça:
struct<typename T>
{
void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};
Ainsi, CreateOtherClass()
lancera ssi le constructeur par défaut du type donné lance. Cela corrige l'un des problèmes majeurs des spécificateurs d'exceptions: leur incapacité à propager la pile d'appels.
Vous ne pouvez pas faire cela avec throw()
.
noexcept
n'est pas vérifié au moment de la compilation.
Une implémentation ne doit pas rejeter une expression simplement parce que lorsqu'elle est exécutée, elle déclenche ou peut lever une exception que la fonction conteneur ne permet pas.
Lorsqu'une fonction déclarée noexcept
ou throw()
tente de lever une exception, la seule différence est que l'on appelle terminate
et les autres appels unexpected
et le ce dernier style de gestion des exceptions est en fait obsolète.
std :: inattendu () est appelé par le runtime C++ lorsqu'une spécification d'exception dynamique est violée: une exception est levée à partir d'une fonction dont la spécification d'exception interdit les exceptions de ce type.
std :: inattendu () peut également être appelé directement à partir du programme.
Dans les deux cas, std :: inattendu appelle le std :: unlimited_handler actuellement installé. Le std :: unlimited_handler par défaut appelle std :: terminate.