On Sunday, April 27, 2025, Jason McKesson wrote:
No. There is nothing fundamentally wrong with calling a function that
*might* throw exceptions from one that won't.
You have no idea what could cause the possibly throwing function to
throw. Maybe there are certain parameters that would cause it to throw
(nullptr, index-out-of-bounds, etc), but the non-throwing function
already did the check and no throwing can ever happen.
Unless you *know* for certain that this is not the case, you have no
right to decide for other people that this code is ill-formed.
Let's say a 3rd party library has a function as follows:
bool RegisterMatrix(unsigned x, unsigned y) noexcept(false);
And let's say that the instruction manual says:
Throws: An object of type 'dimensions_invalid' if 'y' is not a multiple of 'x'.
And then in your own code you invoke this function as follows:
bool RecordAdd(unsigned const x) noexcept
{
return RegisterMatrix(x, x * 4u);
}
In this instance, we know that RegisterMatrix definitely won't throw an exception because we set the 'y' argument equal to 'four times X'. So now let's try force a compiler error with 'noexcept(explicit)' as follows:
bool RecordAdd(unsigned const x) noexcept(explicit)
{
return RegisterMatrix(x, x * 4u);
}
Now the compiler refuses to compile the code because it sees a 'noexcept(false)' function called from a 'noexcept(true)' function. Here we need to tell the compiler that RegisterMatrix won't throw, perhaps by using 'std::won't_throw' as follows:
bool RecordAdd(unsigned const x) noexcept(explicit)
{
return std::wont_throw( RegisterMatrix, x, x * 4u );
}