Liste de diffusion obsolète en C ++ 11

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:

    • Les spécifications d’exception entraînent la fin du programme (ou plus précisément l’appel des gestionnaires de terminaison) si l’implémentation n’a pas réussi à garantir la garantie de ne lancer que les exceptions définies.
    • Ainsi, en appelant une méthode avec une spécification d’exception, vous, en tant qu’utilisateur de bibliothèque, rendz votre propre code plus enclin à une défaillance / résiliation complète. Si la fonction de bibliothèque est en dehors de la mémoire (std :: bad_alloc), vous n’aurez pas la possibilité de l’attraper, mais vous serez interrompu à la place.
    • Ainsi, l’objective initial de communiquer les options d’échec les plus probables et de vous demander en tant qu’utilisateur de les gérer n’a pas été atteint.
    • En tant qu’implémenteur de l’autre côté, vous ne pouvez plus appeler d’autres méthodes qui n’ont pas de spécifications d’exception, car celles-ci pourraient vous amener à mettre fin à vos appels. Un endroit terrible où être

    La conclusion est que C ++ aurait dû disparaître comme le faisait Java:

    • Si vous appelez une méthode avec une spécification d’exception et que vous avez vous-même une spécification d’exception, vous devez intercepter l’exception ou la spécifier dans votre propre spécification d’exception.
    • Le compilateur applique ceci et aucun autre effet d’exécution.

    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.