I'm studying the noexcept
specifier and I am wondering about the reason behind some of its design decision. In particular, the reason why it doesn't make the same compile time checks as, for example, the constexpr
specifier. I will explain this assertion later on.
This is the code I am testing:
#include <iostream>
#include <stdexcept>
void g()
{
throw std::runtime_error("EXCEPT");
}
void f() noexcept
{
g();
}
int main()
{
try
{
f();
}
catch(const std::exception & e)
{
std::cout << "Caught this: " << e.what() << std::endl;
}
return 0;
}
This version of the code compiles but crashes, because (if I understand it well) the with the noexcept
specifier the compiler has just "trusted me" and has made optimization that won't allow the code at runtime to handle any exception, despite the try
/catch
block.
What I do not understand is: why the compiler does not check a simple thing like the signature of g()
? g()
has not been declared noexcept
, so without going on expensive checking if it really throws or not, the code should be just be considered wrong, because g()
is implicitly noexcept(false)
. In which case is this useful?
To work as I personally expected it to work, I have to change the signature of f()
like this:
void f() noexcept(noexcept(g()))
{
g();
}
Now, the noexcept
specifier on f()
declaration is applyied only if it appears in g()
declaration as well. At runtime, the exception is perfectly handled. Why is this not the default? If f()
calls a lot of functions, doing the noexcept(noexcept(g()))
for every called function by hand is a maintenance hell.
I was quoting the constexpr
specifier because it actually makes the compiler check that all those functions called by the constexpr
function are themselves declared as constexpr
. So, I think the reason why noexcept
does not do the same has anything to do with the compilation time.
Summing the question up: why the compiler does not check that the functions called by a noexcept
function are themselves declared as noexcept
?