Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is return throw std::exception() accepted in a void function?

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.

like image 795
Marko Pacak Avatar asked Aug 28 '18 13:08

Marko Pacak


People also ask

What does throw () mean in C++?

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.

Does C++ throw return?

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.

Which type of object is thrown by a throw statement C++?

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);

What do exception allow us to separate?

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.


1 Answers

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 cv void.

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.

like image 123
StoryTeller - Unslander Monica Avatar answered Jan 03 '23 21:01

StoryTeller - Unslander Monica