Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can std::runtime_error::runtime_error(const std::string&) meet std::exception's requirement of throw()?

std::exception requires that its constructor be throw(). Yet std::runtime_error accepts a std::string as its argument, which indicates that it's storing a std::string somewhere. Therefore, an assignment or copy construction has to be going on somewhere. And for std::string, that's not a nothrow operation.

How then does runtime_error::runtime_error meet throw()?

(For context, I'm implementing an exception type, and want to store a few std::strings from the call site, and I want to do it correctly...)

like image 365
Billy ONeal Avatar asked Jul 28 '11 18:07

Billy ONeal


People also ask

What is std :: Runtime_error?

std::runtime_errorDefines a type of object to be thrown as exception. It reports errors that are due to events beyond the scope of the program and can not be easily predicted. Exceptions of type std::runtime_error are thrown by the following standard library components: std::locale::locale and std::locale::combine.

How do you throw a custom exception in C++?

In the main() function, a try-catch block is created to throw and handle the exception. Within the try block, an object of MyCustomException is created and thrown using the throw keyword. The exception is then caught in the catch block, where the message is printed by accessing the what() function.

What are exceptions C++?

Exception handling is a mechanism that separates code that detects and handles exceptional circumstances from the rest of your program. Note that an exceptional circumstance is not necessarily an error.


1 Answers

(Here's the same thing in a minimal-ish testcase.)


runtime_error::runtime_error(string const&) doesn't need to meet throw().

It doesn't inherit from or override exception::exception(), and by the time string's copy constructor is invoked, exception::exception() has completed.

If copying the string were to throw an exception, this would unwind runtime_error::runtime_error(string const&) and then, I suppose, invoke exception::~exception().


It's hard to directly show that there is no requirement of a derived ctor to meet a base ctor's exception specifier, but it is strongly implied by the following passage (which describes how the base's destructor is invoked, rather than passing the exception into the base constructor):

[2003: 15.2/2] An object that is partially constructed or partially destroyed will have destructors executed for all of its fully constructed subobjects, that is, for subobjects for which the constructor has completed execution and the destructor has not yet begun execution. Should a constructor for an element of an automatic array throw an exception, only the constructed elements of that array will be destroyed. If the object or array was allocated in a new-expression, the matching deallocation function (3.7.3.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.

The only passage which comes even close to the scenario you presumed (and which I initially presumed) is the following.

[2003: 15.4/3] If a virtual function has an exception-specification, all declarations, including the definition, of any function that overrides that virtual function in any derived class shall only allow exceptions that are allowed by the exception-specification of the base class virtual function.

But clearly exception::exception() is not a virtual function, and clearly runtime_error::runtime_error(string const&) does not override it.

(Note that this scenario would apply for a virtual destructor; accordingly, you can see that, in libstdc++, runtime_error::~runtime_error() is throw()).

like image 77
Lightness Races in Orbit Avatar answered Nov 02 '22 11:11

Lightness Races in Orbit