Comme je peux le voir dans cppreference , les listes de déclarations classiques “throw” sont maintenant obsolètes en C ++ 11. Quelle est la raison de quitter ce mécanisme et comment devrais-je spécifier quelles exceptions jettent une fonction de la mienne?
Pour un raisonnement plus détaillé, voir: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3051.html
Comme indiqué dans le commentaire de l’organisme national ci-dessus, les spécifications des exceptions ne se sont pas révélées utiles dans la pratique. Il existe de nombreuses discussions sur les problèmes liés aux spécifications d’exception en C ++ (voir, par exemple, [Sutter02], [Boost03]), mais les principaux problèmes sont les suivants:
- Vérification au moment de l’exécution: les spécifications d’exception C ++ sont vérifiées au moment de l’exécution plutôt qu’au moment de la compilation, elles n’offrent donc aucune garantie de programmeur que toutes les exceptions ont été traitées. Le mode de défaillance d’exécution (appelant std :: présence ()) ne se prête pas à une récupération.
- Temps d’exécution: La vérification au moment de l’exécution nécessite que le compilateur produise un code supplémentaire qui entrave également les optimisations.
- Inutilisable en code générique: Dans le code générique, il n’est généralement pas possible de savoir quels types d’exceptions peuvent être générés à partir d’opérations sur des arguments de modèle, de sorte qu’une spécification d’exception précise ne peut pas être écrite.
En pratique, seules deux formes de garanties de lancement d’exception sont utiles: une opération peut déclencher une exception (toute exception) ou une opération ne déclenche jamais d’exception. Le premier s’exprime en omettant complètement la spécification d’exception, tandis que le second peut être exprimé sous la forme throw () mais rarement en raison de considérations de performances.
[N3050] introduit un nouveau type de spécification d’exception, noexcept, spécifie que la fonction ne générera aucune exception. Contrairement à throw (), noexcept n’exige pas que le compilateur introduise du code pour vérifier si une exception est levée. Au contraire, si une fonction spécifiée comme noexcept est sortie via une exception, le résultat est un appel à std :: terminate ().
Avec l’introduction de noexcept, les programmeurs peuvent désormais exprimer les deux types de garanties d’exception utiles dans la pratique, sans surcharge supplémentaire. Cet article propose donc de déprécier les spécifications d’exception “dynamics”, c’est-à-dire celles écrites sous forme de jet (type-id-listopt).
La réponse que Peter a donnée ne pose pas le problème réel des spécifications d’exception pour l’implémenteur et l’utilisateur:
La conclusion est que C ++ aurait dû disparaître comme le faisait Java:
Noexcept (depuis C ++ 11) subit la même erreur conceptuelle, car il provoquera également une terminaison à l’exécution si la spécification n’est pas respectée également, c.-à-d. Cela rend impossible toute utilisation impossible pour les cas graves, mais les cas les plus contenus (les constructeurs de mouvements viennent à l’esprit ).
Ils produisent du code plus lent et plus volumineux, car libc ++ doit vérifier si une exception qui se propage hors d’une fonction viole sa spécification d’exception et appelle std::unexpected
. Ce n’est guère utile, et c’est pire que de simplement documenter les exceptions qu’une fonction vous lance.
Seul le formulaire sans liste de diffusion () est obsolète. Les formulaires sans la liste manquante (int, exception &) , etc. ne sont pas obsolètes.