Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it allowed to throw an exception inside a noexcept-tagged function?

I'm having a hard time understanding this.

double compute(double x, double y) noexcept
{
   if (y == 0)
       throw std::domain_error("y is zero");
   return x / y;
}

this compiles fine in clang (I haven't checked gcc), but it seems nonsense to me. Why would a compiler allow a noexcept function to contain a throw statement?

like image 321
tunnuz Avatar asked Apr 04 '16 01:04

tunnuz


People also ask

What if a Noexcept function throws exception?

When an exception is thrown from a function that is declared noexcept or noexcept(true) , std::terminate is invoked. When an exception is thrown from a function declared as throw() in /std:c++14 mode, the result is undefined behavior. No specific function is invoked.

What is the point of Noexcept?

The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions. It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.

What happens if a function throws an exception that is not listed in the function exception specification list?

If a function throws an exception not listed in its exception specification, the function unexpected(), defined in the C++ standard library, is invoked. The default behavior of unexpected() is to call terminate(). (In some situations, it may be necessary to override the actions performed by unexpected().


2 Answers

What will happen is std::terminate() gets triggered, since your exception specification doesn't allow for this to happen (see [except.spec/9]).

As to why it's allowed, it's simply not possible to exhaustively check if anything violates the specification. Consider something like:

double f(double );
double compute(double x, double y) noexcept
{
    return x / f(y);
} 

Can f throw? Can't say.

like image 139
Barry Avatar answered Oct 19 '22 02:10

Barry


It is possible that a function that claims to not throw will in fact throw.
If a noexcept function does throw, terminate is called, thereby enforcing the promise not to throw at run time.

// The compiler does not check the `noexcept` specification at compile time.
void f() noexcept // Promises to not throw any exception
{
    throw runtime_error("error"); // Violates the exception specification
}

Specifying that a function won't throw promises the callers of the non-throwing function that they will never need to deal with exceptions.

Either the function won't throw or the whole program will terminate.

like image 11
Andreas DM Avatar answered Oct 19 '22 02:10

Andreas DM