I mistakenly pasted a throw
statement after a return
with the following final result:
void DXManager::initialize(const std::shared_ptr<nae::Context>& ctx_ptr)
{
// ...
if (FAILED(result))
{
return throw std::exception("Failed to enumerate display mode list");
}
// ...
}
I successfully built the solution before noticing the mistake, and I'm curious which specification allows the syntax above.
By reading cppreference.com (under Notes), I see
The throw-expression is classified as prvalue expression of type void. Like any other expression, it may be a sub-expression in another expression, most commonly in the conditional operator:
double f(double d) { return d > 1e7 ? throw std::overflow_error("too big") : d; } // ...
but I'm not quite sure it's what I'm looking for.
The throw keyword throws an exception when a problem is detected, which lets us create a custom error. The catch statement allows you to define a block of code to be executed if an error occurs in the try block.
Throwing exceptions from C++ constructors Since C++ constructors do not have a return type, it is not possible to use return codes. Therefore, the best practice is for constructors to throw an exception to signal failure. The throw statement can be used to throw an C++ exception and exit the constructor code.
The throw statement can throw various types of objects. Objects in C++ may generally be thrown by value, reference, or pointer. For example: // throw an object to be caught by value or reference throw EIntegerRange(0, 10, userValue); // throw an object to be caught by pointer throw new EIntegerRange(0, 10, userValue);
The exception stack-unwinding mechanism destroys all objects in scope after an exception is thrown, according to well-defined rules. An exception enables a clean separation between the code that detects the error and the code that handles the error.
Well, it's because a return statement in a function returning void
, can have a void
operand:
[stmt.return]/2
The expr-or-braced-init-list of a return statement is called its operand [...] A return statement with an operand of type
void
shall be used only in a function whose return type is cvvoid
.
And as you found out yourself, a throw
expression has type void
. This provision is there to make writing generic code smoother. Consider this:
template<typename T>
T foo() {
return T();
}
The above rule (along with another rule that defines void()
) make the above template valid even when instantiated for void
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With