Search code examples
c++c++11language-lawyerthrownoexcept

What is the difference between C++03 `throw()` specifier and C++11 `noexcept`?


Is there any difference between throw() and noexcept other than being checked at runtime and compile time respectively?

This Wikipedia C++11 article suggests that the C++03 throw specifiers are deprecated.
Why so ... Is the noexcept capable enough to cover all that at compile time?


Note: I checked this question and this article, but couldn't determine the solid reason for its deprecation.


Solution

  • Exception specifiers were deprecated because exception specifiers are generally a terrible idea. noexcept was added because it's the one reasonably useful use of an exception specifier: knowing when a function won't throw an exception. Thus it becomes a binary choice: functions that will throw and functions that won't throw.

    noexcept was added rather than just removing all throw specifiers other than throw() because noexcept is more powerful. noexcept can have a parameter which compile-time resolves into a boolean. If the boolean is true, then the noexcept sticks. If the boolean is false, then the noexcept doesn't stick and the function may throw.

    Thus, you can do something like this:

    struct<typename T>
    {
      void CreateOtherClass() { T t{}; }
    };
    

    Does CreateOtherClass throw exceptions? It might, if T's default constructor can. How do we tell? Like this:

    struct<typename T>
    {
      void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
    };
    

    Thus, CreateOtherClass() will throw iff the given type's default constructor throws. This fixes one of the major problems with exception specifiers: their inability to propagate up the call stack.

    You can't do this with throw().